68 lines
1.1 KiB
Go
68 lines
1.1 KiB
Go
package ffmpeg
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"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
|
|
err chan error
|
|
fb chan bool
|
|
}
|
|
|
|
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",
|
|
"pipe:1",
|
|
)
|
|
|
|
ff.Cmd.Stderr = os.Stdin
|
|
|
|
// FFmpeg requires a certain buffer size to start writing. This seems to be enough?
|
|
// This will grow big enough to fit the whole song.
|
|
ff.Out = bytes.NewBuffer(make([]byte, 128*1024))
|
|
ff.Cmd.Stdout = ff.Out
|
|
|
|
return
|
|
}
|
|
|
|
func (ff *FFmpeg) Start() error {
|
|
ff.Started = true
|
|
err := ff.Cmd.Start()
|
|
go func() {
|
|
if err != nil {
|
|
ff.err <- ff.Cmd.Wait()
|
|
}
|
|
}()
|
|
|
|
return err
|
|
}
|
|
|
|
func (ff FFmpeg) Close() error {
|
|
ff.Cancel()
|
|
return nil
|
|
}
|