Harden remux timestamp handling
This commit is contained in:
parent
1491d0b0c0
commit
de70448897
144
main.go
144
main.go
|
|
@ -3689,6 +3689,10 @@ func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isDVD := selectedFormat.Ext == ".mpg"
|
isDVD := selectedFormat.Ext == ".mpg"
|
||||||
|
remux := strings.EqualFold(selectedFormat.VideoCodec, "copy")
|
||||||
|
if vc, ok := cfg["videoCodec"].(string); ok && strings.EqualFold(vc, "Copy") {
|
||||||
|
remux = true
|
||||||
|
}
|
||||||
|
|
||||||
// DVD presets: enforce compliant codecs and audio settings
|
// DVD presets: enforce compliant codecs and audio settings
|
||||||
// Note: We do NOT force resolution - user can choose Source or specific resolution
|
// Note: We do NOT force resolution - user can choose Source or specific resolution
|
||||||
|
|
@ -3712,6 +3716,9 @@ func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progre
|
||||||
cfg["pixelFormat"] = "yuv420p"
|
cfg["pixelFormat"] = "yuv420p"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if remux {
|
||||||
|
args = append(args, "-fflags", "+genpts")
|
||||||
|
}
|
||||||
args = append(args, "-i", inputPath)
|
args = append(args, "-i", inputPath)
|
||||||
|
|
||||||
// Add cover art if available
|
// Add cover art if available
|
||||||
|
|
@ -3747,10 +3754,6 @@ func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progre
|
||||||
}
|
}
|
||||||
|
|
||||||
// Video filters
|
// Video filters
|
||||||
remux := strings.EqualFold(selectedFormat.VideoCodec, "copy")
|
|
||||||
if vc, ok := cfg["videoCodec"].(string); ok && strings.EqualFold(vc, "Copy") {
|
|
||||||
remux = true
|
|
||||||
}
|
|
||||||
var vf []string
|
var vf []string
|
||||||
if !remux {
|
if !remux {
|
||||||
// Deinterlacing
|
// Deinterlacing
|
||||||
|
|
@ -3839,67 +3842,66 @@ func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progre
|
||||||
vf = append(vf, scaleFilter)
|
vf = append(vf, scaleFilter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Aspect ratio conversion
|
||||||
|
sourceWidth, _ := cfg["sourceWidth"].(int)
|
||||||
// Aspect ratio conversion
|
sourceHeight, _ := cfg["sourceHeight"].(int)
|
||||||
sourceWidth, _ := cfg["sourceWidth"].(int)
|
// Get source bitrate if present
|
||||||
sourceHeight, _ := cfg["sourceHeight"].(int)
|
sourceBitrate := 0
|
||||||
// Get source bitrate if present
|
if v, ok := cfg["sourceBitrate"].(float64); ok {
|
||||||
sourceBitrate := 0
|
sourceBitrate = int(v)
|
||||||
if v, ok := cfg["sourceBitrate"].(float64); ok {
|
|
||||||
sourceBitrate = int(v)
|
|
||||||
}
|
|
||||||
srcAspect := utils.AspectRatioFloat(sourceWidth, sourceHeight)
|
|
||||||
outputAspect, _ := cfg["outputAspect"].(string)
|
|
||||||
aspectHandling, _ := cfg["aspectHandling"].(string)
|
|
||||||
|
|
||||||
// Create temp source for aspect calculation
|
|
||||||
tempSrc := &videoSource{Width: sourceWidth, Height: sourceHeight}
|
|
||||||
targetAspect := resolveTargetAspect(outputAspect, tempSrc)
|
|
||||||
if targetAspect > 0 && srcAspect > 0 && !utils.RatiosApproxEqual(targetAspect, srcAspect, 0.01) {
|
|
||||||
vf = append(vf, aspectFilters(targetAspect, aspectHandling)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flip horizontal
|
|
||||||
flipH, _ := cfg["flipHorizontal"].(bool)
|
|
||||||
if flipH {
|
|
||||||
vf = append(vf, "hflip")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flip vertical
|
|
||||||
flipV, _ := cfg["flipVertical"].(bool)
|
|
||||||
if flipV {
|
|
||||||
vf = append(vf, "vflip")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotation
|
|
||||||
rotation, _ := cfg["rotation"].(string)
|
|
||||||
if rotation != "" && rotation != "0" {
|
|
||||||
switch rotation {
|
|
||||||
case "90":
|
|
||||||
vf = append(vf, "transpose=1") // 90 degrees clockwise
|
|
||||||
case "180":
|
|
||||||
vf = append(vf, "transpose=1,transpose=1") // 180 degrees
|
|
||||||
case "270":
|
|
||||||
vf = append(vf, "transpose=2") // 90 degrees counter-clockwise (= 270 clockwise)
|
|
||||||
}
|
}
|
||||||
}
|
srcAspect := utils.AspectRatioFloat(sourceWidth, sourceHeight)
|
||||||
|
outputAspect, _ := cfg["outputAspect"].(string)
|
||||||
|
aspectHandling, _ := cfg["aspectHandling"].(string)
|
||||||
|
|
||||||
// Frame rate
|
// Create temp source for aspect calculation
|
||||||
frameRate, _ := cfg["frameRate"].(string)
|
tempSrc := &videoSource{Width: sourceWidth, Height: sourceHeight}
|
||||||
useMotionInterp, _ := cfg["useMotionInterpolation"].(bool)
|
targetAspect := resolveTargetAspect(outputAspect, tempSrc)
|
||||||
if frameRate != "" && frameRate != "Source" {
|
if targetAspect > 0 && srcAspect > 0 && !utils.RatiosApproxEqual(targetAspect, srcAspect, 0.01) {
|
||||||
if useMotionInterp {
|
vf = append(vf, aspectFilters(targetAspect, aspectHandling)...)
|
||||||
// Use motion interpolation for smooth frame rate changes
|
|
||||||
vf = append(vf, fmt.Sprintf("minterpolate=fps=%s:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1", frameRate))
|
|
||||||
} else {
|
|
||||||
// Simple frame rate change (duplicates/drops frames)
|
|
||||||
vf = append(vf, "fps="+frameRate)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if len(vf) > 0 {
|
// Flip horizontal
|
||||||
args = append(args, "-vf", strings.Join(vf, ","))
|
flipH, _ := cfg["flipHorizontal"].(bool)
|
||||||
|
if flipH {
|
||||||
|
vf = append(vf, "hflip")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip vertical
|
||||||
|
flipV, _ := cfg["flipVertical"].(bool)
|
||||||
|
if flipV {
|
||||||
|
vf = append(vf, "vflip")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotation
|
||||||
|
rotation, _ := cfg["rotation"].(string)
|
||||||
|
if rotation != "" && rotation != "0" {
|
||||||
|
switch rotation {
|
||||||
|
case "90":
|
||||||
|
vf = append(vf, "transpose=1") // 90 degrees clockwise
|
||||||
|
case "180":
|
||||||
|
vf = append(vf, "transpose=1,transpose=1") // 180 degrees
|
||||||
|
case "270":
|
||||||
|
vf = append(vf, "transpose=2") // 90 degrees counter-clockwise (= 270 clockwise)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frame rate
|
||||||
|
frameRate, _ := cfg["frameRate"].(string)
|
||||||
|
useMotionInterp, _ := cfg["useMotionInterpolation"].(bool)
|
||||||
|
if frameRate != "" && frameRate != "Source" {
|
||||||
|
if useMotionInterp {
|
||||||
|
// Use motion interpolation for smooth frame rate changes
|
||||||
|
vf = append(vf, fmt.Sprintf("minterpolate=fps=%s:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1", frameRate))
|
||||||
|
} else {
|
||||||
|
// Simple frame rate change (duplicates/drops frames)
|
||||||
|
vf = append(vf, "fps="+frameRate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(vf) > 0 {
|
||||||
|
args = append(args, "-vf", strings.Join(vf, ","))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Video codec
|
// Video codec
|
||||||
|
|
@ -4122,14 +4124,18 @@ func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progre
|
||||||
// DVD-specific parameters are set manually in the video codec section below.
|
// DVD-specific parameters are set manually in the video codec section below.
|
||||||
|
|
||||||
// Fix VFR/desync issues - regenerate timestamps and enforce CFR
|
// Fix VFR/desync issues - regenerate timestamps and enforce CFR
|
||||||
args = append(args, "-fflags", "+genpts")
|
if !remux {
|
||||||
frameRateStr, _ := cfg["frameRate"].(string)
|
args = append(args, "-fflags", "+genpts")
|
||||||
sourceDuration, _ := cfg["sourceDuration"].(float64)
|
frameRateStr, _ := cfg["frameRate"].(string)
|
||||||
if frameRateStr != "" && frameRateStr != "Source" {
|
sourceDuration, _ := cfg["sourceDuration"].(float64)
|
||||||
args = append(args, "-r", frameRateStr)
|
if frameRateStr != "" && frameRateStr != "Source" {
|
||||||
} else if sourceDuration > 0 {
|
args = append(args, "-r", frameRateStr)
|
||||||
// Calculate approximate source frame rate if available
|
} else if sourceDuration > 0 {
|
||||||
args = append(args, "-r", "30") // Safe default
|
// Calculate approximate source frame rate if available
|
||||||
|
args = append(args, "-r", "30") // Safe default
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args = append(args, "-avoid_negative_ts", "make_zero")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Progress feed
|
// Progress feed
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user