package transcode import ( "context" "fmt" "os" ) // Engine converts input audio to PCM WAV using pure Go decoders (no ffmpeg). type Engine struct{} // NewEngine creates a transcoder. The ffmpegPath argument is ignored (kept for config compatibility). func NewEngine(_ string) *Engine { return &Engine{} } func (e *Engine) Available() error { return nil } func (e *Engine) Transcode(ctx context.Context, src, dst string, opt Options) error { if err := opt.Validate(); err != nil { return err } spec, err := ResolveFormat(opt.Format) if err != nil { return err } dst, err = OutputPath(dst, spec.ID) if err != nil { return err } streamer, format, closer, err := openDecoder(src) if err != nil { return err } defer closer.Close() s, format := buildPipeline(streamer, format, opt) samples, err := drainSamples(ctx, s) if err != nil { return err } ch := format.NumChannels if opt.Channels > 0 { ch = opt.Channels } sr := int(format.SampleRate) if opt.SampleRate > 0 { sr = opt.SampleRate } if err := writePCM16WAV(dst, sr, ch, samples); err != nil { return fmt.Errorf("write wav: %w", err) } return nil } func Transcode(ctx context.Context, src, dst string, opt Options) error { return NewEngine("").Transcode(ctx, src, dst, opt) } func ToWhisperWAV(ctx context.Context, src, dst string) error { return Transcode(ctx, src, dst, WhisperOptions()) } // SupportedInputFormats lists file extensions decoded without external tools. func SupportedInputFormats() []string { return append([]string(nil), probeFormats...) } func (e *Engine) Probe(ctx context.Context, path string) (MediaInfo, error) { _ = ctx ext, err := resolveFormat(path) if err != nil { return MediaInfo{}, err } streamer, format, closer, err := openDecoder(path) if err != nil { return MediaInfo{}, err } defer closer.Close() info := MediaInfo{ Format: ext, Streams: []StreamInfo{{ Index: 0, Codec: extTrim(ext), Type: "audio", SampleRate: int(format.SampleRate), Channels: format.NumChannels, }}, } if st, err := os.Stat(path); err == nil { info.BitRate = st.Size() * 8 } _ = streamer return info, nil } func extTrim(ext string) string { if len(ext) > 0 && ext[0] == '.' { return ext[1:] } return ext } // MediaInfo describes decoded input (for optional diagnostics). type MediaInfo struct { Format string `json:"format"` Duration float64 `json:"duration_seconds"` BitRate int64 `json:"bit_rate"` Streams []StreamInfo `json:"streams"` } type StreamInfo struct { Index int `json:"index"` Codec string `json:"codec"` Type string `json:"type"` SampleRate int `json:"sample_rate,omitempty"` Channels int `json:"channels,omitempty"` }