This repository has been archived on 2022-09-20. You can view files and clone it, but cannot push or open issues or pull requests.
go-musicbot/dca0/pcm.go

74 lines
1.9 KiB
Go

// Helper functions for extracting pcm audio from web and local sources.
package dca0
import (
"errors"
"io"
"os/exec"
"strconv"
)
type PcmOptions struct {
FfmpegPath string
Channels int
SampleRate int
// Seek means where to start in seconds.
Seek float32
// Duration means where to stop (in seconds after the time specified by Seek).
// If Duration is set to 0, the stream will ignore it and encode all the way
// to the end of the input.
Duration float32
}
func getDefaultPcmOptions(ffmpegPath string) PcmOptions {
return PcmOptions{
FfmpegPath: ffmpegPath,
Channels: 2,
// 48000 is the only one used by discord currently.
SampleRate: 48000,
Seek: 0,
Duration: 0,
}
}
// Input can be either a local file or an http(s) address. It can be of any
// audio format supported by ffmpeg.
// Wait must be called on the returned command to free its resources after
// everything has been read.
func getPcm(input string, opts PcmOptions) (io.ReadCloser, *exec.Cmd, error) {
if input == "" {
return nil, nil, errors.New("dca0.getPcm() called with empty input")
}
var cmdOpts []string
cmdOpts = append(cmdOpts, []string{
"-vn", // No video.
"-sn", // No subtitle.
"-dn", // No data encoding.
}...)
if opts.Seek != 0.0 {
cmdOpts = append(cmdOpts,
"-accurate_seek",
"-ss", strconv.FormatFloat(float64(opts.Seek), 'f', 5, 32))
}
if opts.Duration != 0.0 {
cmdOpts = append(cmdOpts,
"-t", strconv.FormatFloat(float64(opts.Duration), 'f', 5, 32))
}
cmdOpts = append(cmdOpts, []string{
"-i", input,
"-f", "s16le", // Signed int16 samples.
"-ar", strconv.Itoa(opts.SampleRate),
"-ac", strconv.Itoa(opts.Channels), // Number of audio channels.
"pipe:1", // Output to stdout.
}...)
cmd := exec.Command(opts.FfmpegPath, cmdOpts...)
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, nil, err
}
if err := cmd.Start(); err != nil {
return nil, nil, err
}
return stdout, cmd, nil
}