Implement DVD format FFmpeg codec selection and settings
Critical fix: When a DVD format (NTSC or PAL) is selected, now properly override the video and audio codec to use DVD-compliant standards: Video: - Forces MPEG-2 codec (mpeg2video) - NTSC: 6000k bitrate, 9000k max, gop=15 - PAL: 8000k bitrate, 9500k max, gop=12 Audio: - Forces AC-3 codec for DVD container compatibility - 192 kbps bitrate - 48 kHz sample rate (DVD standard) - Stereo channels (2) This ensures that selecting a DVD format produces DVDStyler-compatible MPEG files without codec errors. Previously, the code was using the default H.264 + AAC, which caused 'unsupported audio codec' errors when trying to write to MPEG container. Fixes the issue where DVD conversions were failing with: 'Unsupported audio codec. Must be one of mp1, mp2, mp3, 16-bit pcm_dvd, pcm_s16be, ac3 or dts.'
This commit is contained in:
parent
3e0d30d425
commit
deb2a27796
122
main.go
122
main.go
|
|
@ -890,70 +890,103 @@ func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progre
|
||||||
args = append(args, "-vf", strings.Join(vf, ","))
|
args = append(args, "-vf", strings.Join(vf, ","))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if this is a DVD format (special handling required)
|
||||||
|
selectedFormat, _ := cfg["selectedFormat"].(formatOption)
|
||||||
|
isDVD := selectedFormat.Ext == ".mpg"
|
||||||
|
|
||||||
// Video codec
|
// Video codec
|
||||||
videoCodec, _ := cfg["videoCodec"].(string)
|
videoCodec, _ := cfg["videoCodec"].(string)
|
||||||
if videoCodec == "Copy" {
|
if videoCodec == "Copy" && !isDVD {
|
||||||
args = append(args, "-c:v", "copy")
|
args = append(args, "-c:v", "copy")
|
||||||
} else {
|
} else {
|
||||||
// Determine the actual codec to use
|
// Determine the actual codec to use
|
||||||
actualCodec := determineVideoCodec(convertConfig{
|
var actualCodec string
|
||||||
VideoCodec: videoCodec,
|
if isDVD {
|
||||||
HardwareAccel: hardwareAccel,
|
// DVD requires MPEG-2 video
|
||||||
})
|
actualCodec = "mpeg2video"
|
||||||
|
} else {
|
||||||
|
actualCodec = determineVideoCodec(convertConfig{
|
||||||
|
VideoCodec: videoCodec,
|
||||||
|
HardwareAccel: hardwareAccel,
|
||||||
|
})
|
||||||
|
}
|
||||||
args = append(args, "-c:v", actualCodec)
|
args = append(args, "-c:v", actualCodec)
|
||||||
|
|
||||||
// Bitrate mode and quality
|
// DVD-specific video settings
|
||||||
bitrateMode, _ := cfg["bitrateMode"].(string)
|
if isDVD {
|
||||||
if bitrateMode == "CRF" || bitrateMode == "" {
|
// NTSC vs PAL settings
|
||||||
crfStr, _ := cfg["crf"].(string)
|
if strings.Contains(selectedFormat.Label, "NTSC") {
|
||||||
if crfStr == "" {
|
args = append(args, "-b:v", "6000k", "-maxrate", "9000k", "-bufsize", "1835k", "-g", "15")
|
||||||
quality, _ := cfg["quality"].(string)
|
} else if strings.Contains(selectedFormat.Label, "PAL") {
|
||||||
crfStr = crfForQuality(quality)
|
args = append(args, "-b:v", "8000k", "-maxrate", "9500k", "-bufsize", "2228k", "-g", "12")
|
||||||
}
|
}
|
||||||
if actualCodec == "libx264" || actualCodec == "libx265" || actualCodec == "libvpx-vp9" {
|
} else {
|
||||||
args = append(args, "-crf", crfStr)
|
// Standard bitrate mode and quality for non-DVD
|
||||||
|
bitrateMode, _ := cfg["bitrateMode"].(string)
|
||||||
|
if bitrateMode == "CRF" || bitrateMode == "" {
|
||||||
|
crfStr, _ := cfg["crf"].(string)
|
||||||
|
if crfStr == "" {
|
||||||
|
quality, _ := cfg["quality"].(string)
|
||||||
|
crfStr = crfForQuality(quality)
|
||||||
|
}
|
||||||
|
if actualCodec == "libx264" || actualCodec == "libx265" || actualCodec == "libvpx-vp9" {
|
||||||
|
args = append(args, "-crf", crfStr)
|
||||||
|
}
|
||||||
|
} else if bitrateMode == "CBR" {
|
||||||
|
if videoBitrate, _ := cfg["videoBitrate"].(string); videoBitrate != "" {
|
||||||
|
args = append(args, "-b:v", videoBitrate, "-minrate", videoBitrate, "-maxrate", videoBitrate, "-bufsize", videoBitrate)
|
||||||
|
}
|
||||||
|
} else if bitrateMode == "VBR" {
|
||||||
|
if videoBitrate, _ := cfg["videoBitrate"].(string); videoBitrate != "" {
|
||||||
|
args = append(args, "-b:v", videoBitrate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if bitrateMode == "CBR" {
|
|
||||||
if videoBitrate, _ := cfg["videoBitrate"].(string); videoBitrate != "" {
|
|
||||||
args = append(args, "-b:v", videoBitrate, "-minrate", videoBitrate, "-maxrate", videoBitrate, "-bufsize", videoBitrate)
|
|
||||||
}
|
|
||||||
} else if bitrateMode == "VBR" {
|
|
||||||
if videoBitrate, _ := cfg["videoBitrate"].(string); videoBitrate != "" {
|
|
||||||
args = append(args, "-b:v", videoBitrate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encoder preset
|
// Encoder preset
|
||||||
if encoderPreset, _ := cfg["encoderPreset"].(string); encoderPreset != "" && (actualCodec == "libx264" || actualCodec == "libx265") {
|
if encoderPreset, _ := cfg["encoderPreset"].(string); encoderPreset != "" && (actualCodec == "libx264" || actualCodec == "libx265") {
|
||||||
args = append(args, "-preset", encoderPreset)
|
args = append(args, "-preset", encoderPreset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pixel format
|
// Pixel format
|
||||||
if pixelFormat, _ := cfg["pixelFormat"].(string); pixelFormat != "" {
|
if pixelFormat, _ := cfg["pixelFormat"].(string); pixelFormat != "" {
|
||||||
args = append(args, "-pix_fmt", pixelFormat)
|
args = append(args, "-pix_fmt", pixelFormat)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio codec and settings
|
// Audio codec and settings
|
||||||
audioCodec, _ := cfg["audioCodec"].(string)
|
audioCodec, _ := cfg["audioCodec"].(string)
|
||||||
if audioCodec == "Copy" {
|
if audioCodec == "Copy" && !isDVD {
|
||||||
args = append(args, "-c:a", "copy")
|
args = append(args, "-c:a", "copy")
|
||||||
} else {
|
} else {
|
||||||
actualAudioCodec := determineAudioCodec(convertConfig{AudioCodec: audioCodec})
|
var actualAudioCodec string
|
||||||
|
if isDVD {
|
||||||
|
// DVD requires AC-3 audio
|
||||||
|
actualAudioCodec = "ac3"
|
||||||
|
} else {
|
||||||
|
actualAudioCodec = determineAudioCodec(convertConfig{AudioCodec: audioCodec})
|
||||||
|
}
|
||||||
args = append(args, "-c:a", actualAudioCodec)
|
args = append(args, "-c:a", actualAudioCodec)
|
||||||
|
|
||||||
if audioBitrate, _ := cfg["audioBitrate"].(string); audioBitrate != "" && actualAudioCodec != "flac" {
|
// DVD-specific audio settings
|
||||||
args = append(args, "-b:a", audioBitrate)
|
if isDVD {
|
||||||
}
|
// DVD standard: AC-3 stereo at 48 kHz, 192 kbps
|
||||||
|
args = append(args, "-b:a", "192k", "-ar", "48000", "-ac", "2")
|
||||||
|
} else {
|
||||||
|
// Standard audio settings for non-DVD
|
||||||
|
if audioBitrate, _ := cfg["audioBitrate"].(string); audioBitrate != "" && actualAudioCodec != "flac" {
|
||||||
|
args = append(args, "-b:a", audioBitrate)
|
||||||
|
}
|
||||||
|
|
||||||
if audioChannels, _ := cfg["audioChannels"].(string); audioChannels != "" && audioChannels != "Source" {
|
if audioChannels, _ := cfg["audioChannels"].(string); audioChannels != "" && audioChannels != "Source" {
|
||||||
switch audioChannels {
|
switch audioChannels {
|
||||||
case "Mono":
|
case "Mono":
|
||||||
args = append(args, "-ac", "1")
|
args = append(args, "-ac", "1")
|
||||||
case "Stereo":
|
case "Stereo":
|
||||||
args = append(args, "-ac", "2")
|
args = append(args, "-ac", "2")
|
||||||
case "5.1":
|
case "5.1":
|
||||||
args = append(args, "-ac", "6")
|
args = append(args, "-ac", "6")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -965,8 +998,7 @@ func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progre
|
||||||
args = append(args, "-disposition:v:1", "attached_pic")
|
args = append(args, "-disposition:v:1", "attached_pic")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format-specific settings
|
// Format-specific settings (already parsed above for DVD check)
|
||||||
var selectedFormat formatOption
|
|
||||||
switch v := cfg["selectedFormat"].(type) {
|
switch v := cfg["selectedFormat"].(type) {
|
||||||
case formatOption:
|
case formatOption:
|
||||||
selectedFormat = v
|
selectedFormat = v
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user