kvm/audio.go

82 lines
1.8 KiB
Go

package kvm
import (
"fmt"
"net"
"os/exec"
"sync"
"syscall"
"time"
)
func startFFmpeg() (cmd *exec.Cmd, err error) {
binaryPath := "/userdata/jetkvm/bin/ffmpeg"
// Run the binary in the background
cmd = exec.Command(binaryPath,
"-f", "alsa",
"-channels", "2",
"-sample_rate", "48000",
"-i", "hw:1,0",
"-c:a", "libopus",
"-b:a", "64k", // ought to be enough for anybody
"-vbr", "off",
"-frame_duration", "20",
"-compression_level", "2",
"-f", "rtp",
"rtp://127.0.0.1:3333")
nativeOutputLock := sync.Mutex{}
nativeStdout := &nativeOutput{
mu: &nativeOutputLock,
logger: nativeLogger.Info().Str("pipe", "stdout"),
}
nativeStderr := &nativeOutput{
mu: &nativeOutputLock,
logger: nativeLogger.Info().Str("pipe", "stderr"),
}
// Redirect stdout and stderr to the current process
cmd.Stdout = nativeStdout
cmd.Stderr = nativeStderr
// Set the process group ID so we can kill the process and its children when this process exits
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
Pdeathsig: syscall.SIGKILL,
}
// Start the command
if err := cmd.Start(); err != nil {
return nil, fmt.Errorf("failed to start binary: %w", err)
}
return
}
func StartNtpAudioServer(handleClient func(net.Conn)) {
scopedLogger := nativeLogger.With().
Logger()
listener, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 3333})
if err != nil {
scopedLogger.Warn().Err(err).Msg("failed to start server")
return
}
scopedLogger.Info().Msg("server listening")
go func() {
for {
cmd, err := startFFmpeg()
if err != nil {
scopedLogger.Error().Err(err).Msg("failed to start ffmpeg")
}
err = cmd.Wait()
scopedLogger.Error().Err(err).Msg("ffmpeg exited, restarting")
time.Sleep(2 * time.Second)
}
}()
go handleClient(listener)
}