From 2055dccfbb3812e884928d9eb054c6652ef80ee4 Mon Sep 17 00:00:00 2001 From: Tohru <65994850+Tohrusky@users.noreply.github.com> Date: Sat, 4 Jan 2025 23:01:22 +0000 Subject: [PATCH] refactor: improve ReMux logic with fallback codec combinations (#67) * fix: typo `func ClaerTempFile` --- module/ffmpeg/cut.go | 4 +- module/ffmpeg/merge.go | 125 ++++++++++++++++++++----------- module/ffmpeg/vapoursynth.go | 4 +- module/util/file.go | 4 +- worker/internal/cut/worker.go | 4 +- worker/internal/encode/worker.go | 4 +- worker/internal/merge/worker.go | 4 +- 7 files changed, 93 insertions(+), 56 deletions(-) diff --git a/module/ffmpeg/cut.go b/module/ffmpeg/cut.go index ffa7d92..ed1441d 100644 --- a/module/ffmpeg/cut.go +++ b/module/ffmpeg/cut.go @@ -35,10 +35,10 @@ func CutVideo(inputPath string, outputFolder string) ([]string, error) { } // 清理临时文件 - _ = util.ClaerTempFile(scriptPath) + _ = util.ClearTempFile(scriptPath) defer func(p ...string) { log.Logger.Infof("Clear temp file %v", p) - _ = util.ClaerTempFile(p...) + _ = util.ClearTempFile(p...) }(scriptPath) // 写入脚本文件 diff --git a/module/ffmpeg/merge.go b/module/ffmpeg/merge.go index 0cd1101..06b621a 100644 --- a/module/ffmpeg/merge.go +++ b/module/ffmpeg/merge.go @@ -10,15 +10,15 @@ import ( ) // MergeVideo 使用 ffmpeg 进行视频合并,使用 mkvpropedit 清除 tags -func MergeVideo(originFile string, inputFiles []string, outputPath string) error { +func MergeVideo(originPath string, inputFiles []string, outputPath string) error { listPath := "temp_list.txt" // 写入文件列表 tempVideoConcatOutputPath := "temp_video_concat_output.mkv" // clear temp file - _ = util.ClaerTempFile(listPath, tempVideoConcatOutputPath) + _ = util.ClearTempFile(listPath, tempVideoConcatOutputPath) defer func(p ...string) { log.Logger.Infof("Clear temp file %v", p) - _ = util.ClaerTempFile(p...) + _ = util.ClearTempFile(p...) }(listPath, tempVideoConcatOutputPath) var listStr string @@ -49,48 +49,11 @@ func MergeVideo(originFile string, inputFiles []string, outputPath string) error } log.Logger.Infof("Concat video output: %s", out) - // Merge video - log.Logger.Infof("Merge video with concat output: %s", tempVideoConcatOutputPath) - // audio track + subtitle track - cmd = exec.Command( - "ffmpeg", - "-i", originFile, - "-i", tempVideoConcatOutputPath, - "-map", "1:v:0", - "-map", "0:a", - "-map", "0:s", - "-disposition:v:0", "default", - "-c:v", "copy", - "-c:a", "flac", - "-c:s", "copy", - "-max_interleave_delta", "0", - outputPath, - ) - out, err = cmd.CombinedOutput() - log.Logger.Infof("Merged output: %s", out) + // ReMuxWithSourceVideo + err = ReMuxWithSourceVideo(originPath, outputPath, tempVideoConcatOutputPath) if err != nil { - // clean maybe failed output - _ = util.ClaerTempFile(outputPath) - log.Logger.Errorf("Merge audio with audio and subtitle failed: %v, try to merge audio only", err) - // audio track - cmd = exec.Command( - "ffmpeg", - "-i", originFile, - "-i", tempVideoConcatOutputPath, - "-map", "1:v:0", - "-map", "0:a", - "-disposition:v:0", "default", - "-c:v", "copy", - "-c:a", "flac", - "-max_interleave_delta", "0", - outputPath, - ) - out, err = cmd.CombinedOutput() - log.Logger.Infof("Merged output: %s", out) - if err != nil { - log.Logger.Errorf("Merge audio failed: %v", err) - return err - } + log.Logger.Errorf("ReMux with source video failed: %v", err) + return err } // Remove tags with mkvpropedit @@ -108,3 +71,77 @@ func MergeVideo(originFile string, inputFiles []string, outputPath string) error log.Logger.Infof("Remove tags output: %s", out) return nil } + +// ReMuxWithSourceVideo 使用 ffmpeg 和原始视频进行 remux +func ReMuxWithSourceVideo(originPath string, outputPath string, concatOutputPath string) error { + // Define the different codec combinations to try + codecCombinations := [][]string{ + // Try copying both audio and subtitles + { + "-map", "1:v:0", + "-map", "0:a", + "-map", "0:s", + "-disposition:v:0", "default", + "-c:v", "copy", + "-c:a", "copy", + "-c:s", "copy", + "-max_interleave_delta", "0", + }, + // Try FLAC for audio and copy subtitles + { + "-map", "1:v:0", + "-map", "0:a", + "-map", "0:s", + "-disposition:v:0", "default", + "-c:v", "copy", + "-c:a", "flac", + "-c:s", "copy", + "-max_interleave_delta", "0", + }, + // Try copying only audio + { + "-map", "1:v:0", + "-map", "0:a", + "-disposition:v:0", "default", + "-c:v", "copy", + "-c:a", "copy", + "-max_interleave_delta", "0", + }, + // Try FLAC for audio only + { + "-map", "1:v:0", + "-map", "0:a", + "-disposition:v:0", "default", + "-c:v", "copy", + "-c:a", "flac", + "-max_interleave_delta", "0", + }, + } + + // Iterate over each codec combination + for _, codecArgs := range codecCombinations { + // Build the ffmpeg command with the current codec combination + args := []string{ + "-i", originPath, + "-i", concatOutputPath, + } + args = append(args, codecArgs...) + args = append(args, outputPath) + + cmd := exec.Command("ffmpeg", args...) + out, err := cmd.CombinedOutput() + log.Logger.Infof("ffmpeg remux output with codec combination %v: %s", codecArgs, out) + + if err == nil { + // Success, return nil + return nil + } + + // Log the error and try the next combination + log.Logger.Errorf("ffmpeg remux failed with codec combination %v: %v", codecArgs, err) + // If failed, clean up temp files which may have been created + _ = util.ClearTempFile(outputPath) + } + + return fmt.Errorf("ffmpeg remux: all codec combinations failed") +} diff --git a/module/ffmpeg/vapoursynth.go b/module/ffmpeg/vapoursynth.go index b26f1bf..938b92e 100644 --- a/module/ffmpeg/vapoursynth.go +++ b/module/ffmpeg/vapoursynth.go @@ -29,10 +29,10 @@ func EncodeVideo(encodeScript string, encodeParam string) error { log.Logger.Info("commandStr: " + commandStr) // 清理临时文件 - _ = util.ClaerTempFile(encodeScriptPath, scriptPath) + _ = util.ClearTempFile(encodeScriptPath, scriptPath) defer func(p ...string) { log.Logger.Infof("Clear temp file %v", p) - _ = util.ClaerTempFile(p...) + _ = util.ClearTempFile(p...) }(encodeScriptPath, scriptPath) // 写入压制 py diff --git a/module/util/file.go b/module/util/file.go index 06fa68b..ba61508 100644 --- a/module/util/file.go +++ b/module/util/file.go @@ -14,8 +14,8 @@ func ByteCountBinary(b uint64) string { return humanize.BigIBytes(bigInt) } -// ClaerTempFile 清理临时文件 -func ClaerTempFile(tempPath ...string) error { +// ClearTempFile 清理临时文件 +func ClearTempFile(tempPath ...string) error { for _, p := range tempPath { err := os.RemoveAll(p) if err != nil { diff --git a/worker/internal/cut/worker.go b/worker/internal/cut/worker.go index 8006193..2198bef 100644 --- a/worker/internal/cut/worker.go +++ b/worker/internal/cut/worker.go @@ -39,10 +39,10 @@ func Handler(ctx context.Context, t *asynq.Task) error { tempVideo := tempPath + path.Ext(p.VideoKey) // 清理临时文件 - _ = util.ClaerTempFile(tempPath, tempVideo) + _ = util.ClearTempFile(tempPath, tempVideo) defer func(p ...string) { log.Logger.Infof("Clear temp file %v", p) - _ = util.ClaerTempFile(p...) + _ = util.ClearTempFile(p...) }(tempPath, tempVideo) _ = os.Mkdir(tempPath, os.ModePerm) diff --git a/worker/internal/encode/worker.go b/worker/internal/encode/worker.go index 5d9fca2..0577136 100644 --- a/worker/internal/encode/worker.go +++ b/worker/internal/encode/worker.go @@ -44,10 +44,10 @@ func Handler(ctx context.Context, t *asynq.Task) error { tempEncodedVideo := "encoded.mkv" // 清理临时文件 - _ = util.ClaerTempFile(tempSourceVideo, tempEncodedVideo) + _ = util.ClearTempFile(tempSourceVideo, tempEncodedVideo) defer func(p ...string) { log.Logger.Infof("Clear temp file %v", p) - _ = util.ClaerTempFile(p...) + _ = util.ClearTempFile(p...) }(tempSourceVideo, tempEncodedVideo) // 等待下载完成 diff --git a/worker/internal/merge/worker.go b/worker/internal/merge/worker.go index dc3ae5e..15b758f 100644 --- a/worker/internal/merge/worker.go +++ b/worker/internal/merge/worker.go @@ -46,10 +46,10 @@ func Handler(ctx context.Context, t *asynq.Task) error { tempMergedFile := "temp_merged.mkv" // 清理临时文件 - _ = util.ClaerTempFile(tempFolder, tempOriginFile, tempMergedFile) + _ = util.ClearTempFile(tempFolder, tempOriginFile, tempMergedFile) defer func(p ...string) { log.Logger.Infof("Clear temp file %v", p) - _ = util.ClaerTempFile(p...) + _ = util.ClearTempFile(p...) }(tempFolder, tempOriginFile, tempMergedFile) _ = os.Mkdir(tempFolder, os.ModePerm)