mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 15:05:39 +02:00
harden ffmpeg pipeline failure handling and stream mapping
This commit is contained in:
@@ -323,17 +323,7 @@ func (d *Downloader) streamManifestWithFFmpeg(ctx context.Context, sourceURL, ou
|
||||
return fmt.Errorf("ffmpeg not found for manifest stream: %w", err)
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-y",
|
||||
"-protocol_whitelist", "file,http,https,tcp,tls,crypto,data",
|
||||
"-i", sourceURL,
|
||||
}
|
||||
if includeVideo {
|
||||
args = append(args, "-map", "0")
|
||||
} else {
|
||||
args = append(args, "-map", "0:a:0")
|
||||
}
|
||||
args = append(args, "-c", "copy", "-hide_banner", "-nostats", "-progress", "pipe:2", outputPath)
|
||||
args := buildFFmpegStreamArgs(sourceURL, outputPath, includeVideo)
|
||||
|
||||
if !d.ProgressEnabled() {
|
||||
cmd := exec.CommandContext(ctx, "ffmpeg", args...)
|
||||
@@ -458,6 +448,24 @@ func (d *Downloader) streamManifestWithFFmpeg(ctx context.Context, sourceURL, ou
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildFFmpegStreamArgs(sourceURL, outputPath string, includeVideo bool) []string {
|
||||
args := []string{
|
||||
"-y",
|
||||
"-protocol_whitelist", "file,http,https,tcp,tls,crypto,data",
|
||||
"-i", sourceURL,
|
||||
}
|
||||
if includeVideo {
|
||||
args = append(args,
|
||||
"-map", "0:v:0?",
|
||||
"-map", "0:a:0?",
|
||||
)
|
||||
} else {
|
||||
args = append(args, "-map", "0:a:0")
|
||||
}
|
||||
args = append(args, "-c", "copy", "-hide_banner", "-nostats", "-progress", "pipe:2", outputPath)
|
||||
return args
|
||||
}
|
||||
|
||||
type scanState struct {
|
||||
totalMS int64
|
||||
currentMS int64
|
||||
|
||||
@@ -260,3 +260,38 @@ func TestParseClockDurationMSInvalid(t *testing.T) {
|
||||
t.Fatalf("expected short duration to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildFFmpegStreamArgsAudioOnly(t *testing.T) {
|
||||
args := buildFFmpegStreamArgs("https://example.com/master.m3u8", "/tmp/out.m4a", false)
|
||||
if !containsArgPair(args, "-map", "0:a:0") {
|
||||
t.Fatalf("expected audio map in args: %v", args)
|
||||
}
|
||||
if containsArgPair(args, "-map", "0:v:0?") {
|
||||
t.Fatalf("did not expect video map in audio-only args: %v", args)
|
||||
}
|
||||
if containsArgPair(args, "-map", "0") {
|
||||
t.Fatalf("did not expect broad map=0 in args: %v", args)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildFFmpegStreamArgsIncludeVideo(t *testing.T) {
|
||||
args := buildFFmpegStreamArgs("https://example.com/master.m3u8", "/tmp/out.mp4", true)
|
||||
if !containsArgPair(args, "-map", "0:v:0?") {
|
||||
t.Fatalf("expected video map in args: %v", args)
|
||||
}
|
||||
if !containsArgPair(args, "-map", "0:a:0?") {
|
||||
t.Fatalf("expected audio map in args: %v", args)
|
||||
}
|
||||
if containsArgPair(args, "-map", "0") {
|
||||
t.Fatalf("did not expect broad map=0 in args: %v", args)
|
||||
}
|
||||
}
|
||||
|
||||
func containsArgPair(args []string, key, value string) bool {
|
||||
for i := 0; i+1 < len(args); i++ {
|
||||
if args[i] == key && args[i+1] == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user