BuildArgs hardcoded -map 0✌️0 / -map 0🅰️0 for the two RTP legs. Correct for production RTMP/SRT publishers (single combined input), but breaks any process whose audio lives on a different input index — multi-input lavfi test scaffolds, multi-camera pipelines, SDI + file-audio mixes, etc. Adds VideoMap and AudioMap fields to ConfigWebRTC (and the API DTO), defaulting to the prior literals so existing deployments are unaffected. BuildArgs reads them. Tests: - TestBuildArgs_DefaultMaps locks the empty-string default behavior - TestBuildArgs_CustomMaps drives the multi-input override path - TestProcessConfigWebRTCMapsRoundtrip extends the DTO roundtrip Closes #2. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
61 lines
1.7 KiB
Go
61 lines
1.7 KiB
Go
package webrtc
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
appcfg "github.com/datarhei/core/v16/restream/app"
|
|
)
|
|
|
|
// BuildArgs emits the FFmpeg output-leg args for the WebRTC side of a
|
|
// process. It produces two separate "outputs" — one for video on
|
|
// videoPort, one for audio on videoPort+1. Each output ends with its
|
|
// UDP address so the slice is structured for consumption by
|
|
// restream.AppendOutput after splitting on the track boundary.
|
|
//
|
|
// Copy vs. re-encode: if ForceTranscode is false, we assume the upstream
|
|
// source is already H.264 + Opus and pass them through (copy). When the
|
|
// source doesn't match, FFmpeg will fail at runtime and the process will
|
|
// restart — the user can flip ForceTranscode on to get a baseline-profile
|
|
// H.264 + Opus re-encode.
|
|
func BuildArgs(cfg appcfg.ConfigWebRTC, videoPort int) []string {
|
|
vcopy := []string{"-c:v", "copy"}
|
|
acopy := []string{"-c:a", "copy"}
|
|
if cfg.ForceTranscode {
|
|
vcopy = []string{
|
|
"-c:v", "libx264",
|
|
"-preset", "veryfast",
|
|
"-profile:v", "baseline",
|
|
"-pix_fmt", "yuv420p",
|
|
"-tune", "zerolatency",
|
|
"-g", "60",
|
|
}
|
|
acopy = []string{"-c:a", "libopus", "-b:a", "96k"}
|
|
}
|
|
|
|
videoMap := cfg.VideoMap
|
|
if videoMap == "" {
|
|
videoMap = "0:v:0"
|
|
}
|
|
audioMap := cfg.AudioMap
|
|
if audioMap == "" {
|
|
audioMap = "0:a:0"
|
|
}
|
|
|
|
args := []string{"-map", videoMap}
|
|
args = append(args, vcopy...)
|
|
args = append(args,
|
|
"-payload_type", fmt.Sprint(cfg.VideoPT),
|
|
"-f", "rtp",
|
|
fmt.Sprintf("udp://127.0.0.1:%d?pkt_size=1316", videoPort),
|
|
)
|
|
|
|
args = append(args, "-map", audioMap)
|
|
args = append(args, acopy...)
|
|
args = append(args,
|
|
"-payload_type", fmt.Sprint(cfg.AudioPT),
|
|
"-f", "rtp",
|
|
fmt.Sprintf("udp://127.0.0.1:%d?pkt_size=1316", videoPort+1),
|
|
)
|
|
|
|
return args
|
|
}
|