package ffmpeg import ( "bytes" "context" "log" "os" "os/exec" "strconv" "time" ) type FFmpeg struct { Out *bytes.Buffer Cmd *exec.Cmd Started bool Cancel context.CancelFunc Len time.Duration Title string Channel string } func NewFFmpeg(uri string, sampleRate int, channels int) (ff *FFmpeg, err error) { ff = new(FFmpeg) ctx, cancel := context.WithCancel(context.Background()) ff.Cancel = cancel ff.Cmd = exec.CommandContext( ctx, "ffmpeg", "-i", uri, "-f", "s16le", "-v", "error", //"-stats", "-ar", strconv.Itoa(sampleRate), "-ac", strconv.Itoa(channels), "-af", "loudnorm=I=-16:LRA=11:TP=-1.5", "-threads", "4", "pipe:1", ) ff.Cmd.Stderr = os.Stdin ff.Out = bytes.NewBuffer(make([]byte, 1024)) ff.Cmd.Stdout = ff.Out return } func (ff *FFmpeg) Start() error { err := ff.Cmd.Start() if err != nil { return err } // We need to wait till the buffer starts filling up.. for ff.Out.Len() == 1024 { } ff.Started = true go func() { // Wait till this is empty.. log.Println(ff.Cmd.Wait()) }() return err } func (ff FFmpeg) Close() error { ff.Cancel() return nil }