package transcode import "time" // 三层上限 + 并发 + 超时的默认取值(design/25 §2.5,取值照设计,不得自行改)。 // 全部具名:本包不存在裸数字。 const ( // DefaultMaxInputBytes 是单次转码的输入字节上限(5 MiB)。取值与 // mediafetch.MaxVoiceBytes 相同但**不共用常量**:一个是「入站内联上限」, // 一个是「转码输入上限」,共用会让「改一个静默改另一个」(design/25 §2.5)。 DefaultMaxInputBytes = 5 << 20 // DefaultMaxOutputBytes 是解码产物的字节上限(64 MiB)。AMR-NB 是唯一会放大的 // 那条路:12.2 kbps ≈ 1525 B/s → 8 kHz 单声道 PCM16 = 16000 B/s ≈ 10.5×, // 加帧头最坏约 12.8×,5 MiB 输入最坏 ⇒ ≈64 MiB。没有这条闸就是 // 「上传 5 MB、内存里长到 64 MB」。 DefaultMaxOutputBytes = 64 << 20 // DefaultMaxDuration 是可确证的时长上限(10 分钟):「正常语音」与「把整段录音 // 伪装成语音」的分界。可从 AMR 帧数确证(一帧 20ms),绝不估算。 DefaultMaxDuration = 10 * time.Minute // DefaultConcurrency 是全局并发槽数(信号量容量)。 DefaultConcurrency = 2 // DefaultTimeout 是单次调用的 ctx 超时上限。 DefaultTimeout = 10 * time.Second ) // Limits 是一次转码的资源约束(design/25 §2.5)。零值字段由 Engine 用上面的 // 具名默认补足,因此 `Limits{}` 是安全的「全默认」。 type Limits struct { // MaxInputBytes 输入字节上限;命中即 ErrInputTooLarge(解码前拒绝)。 MaxInputBytes int // MaxOutputBytes 产物字节上限;命中即 ErrOutputTooLarge。 MaxOutputBytes int // MaxDuration 可确证的时长上限;命中即 ErrInputTooLarge。 MaxDuration time.Duration // Concurrency 全局并发槽数;槽满即 ErrBusy(快速失败,不排队)。 Concurrency int // Timeout 单次调用的超时;命中即 ErrTimeout。 Timeout time.Duration } // DefaultLimits 返回一组全默认的限额(design/25 §2.5 的取值)。 func DefaultLimits() Limits { return Limits{ MaxInputBytes: DefaultMaxInputBytes, MaxOutputBytes: DefaultMaxOutputBytes, MaxDuration: DefaultMaxDuration, Concurrency: DefaultConcurrency, Timeout: DefaultTimeout, } } // withDefaults 用默认值补足零值字段。负数与零一并按「未配置」处理:限额的 // 零值若照字面生效会变成「一字节都不许」,那不是任何调用方想要的行为。 func (l Limits) withDefaults() Limits { if l.MaxInputBytes <= 0 { l.MaxInputBytes = DefaultMaxInputBytes } if l.MaxOutputBytes <= 0 { l.MaxOutputBytes = DefaultMaxOutputBytes } if l.MaxDuration <= 0 { l.MaxDuration = DefaultMaxDuration } if l.Concurrency <= 0 { l.Concurrency = DefaultConcurrency } if l.Timeout <= 0 { l.Timeout = DefaultTimeout } return l }