• C# FFmpeg合并多个音频文件,并指定每段音频的插入时间。


    合成音频的FFmpeg命令为:

    ffmpeg -i 11.wav -i 13.wav -filter_complex "[0]adelay=1s:all=1[0a];[1]adelay=26s:all=1[1a];[0a][1a]amix=inputs=2[a]" -map "[a]" output.wav
    

    不知道具体啥意思,大概猜测一下,
    -i <fileName> 输入文件的路径,有几个文件就几个-i命令
    [0]adelay=1s:all=1[0a] [0]和[0a]指的是第几个文件,索引从0开始,adelay=1s 从音频的第一秒开始插入,默认是毫秒,adelay=1000, 如果加后缀s,则指的秒数,此时不支持小数位写法。(4.2版本以下不支持1s这种写法),all:Use last set delay for all remaining channels. By default is disabled. This option if enabled changes how option delays is interpreted.
    amix=inputs=2 2指的是一共有几个文件
    output.wav 输出文件的路径或者文件名
    文件名都支持全路径的写法。可以是 C:\Data\CHN\Other\FFmpegMergeMp3\11.wav 也可以是 11.wav

    ffmpeg版本:https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-essentials.7z
    latest git master branch build version: 2021-11-25-git-522f577d7e
    使用 <package id="Xabe.FFmpeg" version="5.0.2" targetFramework="net48" /> 包来执行命令

    public static string FFMPEGPath { get; set; } = @"C:\Data\PATHVariables";
    
    static async Task Main(string[] args)
    {
        string inputFile1 = @"C:\Data\CHN\Other\FFmpegMergeMp3\11.wav";
        string inputFile3 = @"C:\Data\CHN\Other\FFmpegMergeMp3\13.wav";
        string outputPath = $@"C:\Data\CHN\Other\FFmpegMergeMp3\{Guid.NewGuid()}.wav";
    
        var listFile = new List<TextToSppechConversionModel>();
        listFile.Add(new TextToSppechConversionModel() { Title = "Section 1", AudioFilePath = inputFile1, StartTime = "00:0:05" });
        listFile.Add(new TextToSppechConversionModel() { Title = "Section 3", AudioFilePath = inputFile3, StartTime = "00:0:15" });
    
        await new Program().CombineAudioToOneFile(listFile, outputPath);
    }
    
    public async Task CombineAudioToOneFile(List<TextToSppechConversionModel> listSourceFile, string outputPath)
    {
        FFmpeg.SetExecutablesPath(FFMPEGPath, "ffmpeg", "ffprobe");
    
        //https://stackoverflow.com/questions/60027460/how-to-add-multiple-audio-files-at-specific-times-on-a-silence-audio-file-using
        //https://www.ffmpeg.org/ffmpeg-all.html#adelay
        //https://ffmpeg.org/ffmpeg-filters.html#amix
        //string inputFile1 = @"C:\Data\CHN\Other\FFmpegMergeMp3\11.wav";
        //string inputFile3 = @"C:\Data\CHN\Other\FFmpegMergeMp3\13.wav";
        //outputPath = $@"C:\Data\CHN\Other\FFmpegMergeMp3\{Guid.NewGuid()}.wav";
    
        //var mediaFile1 = await FFmpeg.GetMediaInfo(inputFile1);
        //var mediaFile3 = await FFmpeg.GetMediaInfo(inputFile3);
    
        //var audioStream1 = mediaFile1.AudioStreams.FirstOrDefault();
        //var audioStream3 = mediaFile3.AudioStreams.FirstOrDefault();
        //audioStream1 = audioStream1.SetCodec(AudioCodec.aac);
        //audioStream3 = audioStream3.SetCodec(AudioCodec.aac);
    
        //var conversion = FFmpeg.Conversions.New().AddStream(new List<IStream>() { audioStream1, audioStream3 }).SetOutput(outputPath);
        /*
            * ffmpeg -i 11.wav -i 13.wav -filter_complex \"[0]adelay=1s:all=1[0a];[1]adelay=26s:all=1[1a];[0a][1a]amix=inputs=2[a]\" 
            * -map \"[a]\" output11132.wav
            */
        //string param = $" -i {inputFile1} -i {inputFile3} -filter_complex \"[0]adelay=1s:all=1[0a];[1]adelay=26s:all=1[1a];[0a][1a]amix=inputs=2[a]\" -map \"[a]\" {outputPath}";
        //var conversionResult = await conversion.Start(param);
    
        StringBuilder sbInputFile = new StringBuilder();
        StringBuilder sbAdelay = new StringBuilder();
        var listStream = new List<IStream>();
        var strA = "";
        for (int i = 0; i < listSourceFile.Count; i++)
        {
            var sourceModel = listSourceFile[i];
            if (!File.Exists(sourceModel.AudioFilePath))
                throw new Exception($"the file {sourceModel.AudioFilePath} not found.");
    
            var mediaFile1 = await FFmpeg.GetMediaInfo(sourceModel.AudioFilePath);
            var audioStream1 = mediaFile1.AudioStreams.FirstOrDefault().SetCodec(AudioCodec.ac3);
            listStream.Add(audioStream1);
            //sourceModel.StartTime;//"00:01:02"
            var timeSpan = DateTime.Parse(sourceModel.StartTime) - DateTime.Parse("00:00:00");
            var startSeconds = timeSpan.TotalSeconds; //seconds
            //check current length
            if (i + 1 < listSourceFile.Count)
            {
                //get next start time
                var nextStartTime = listSourceFile[i + 1].StartTime;
                var timeSpanNext = DateTime.Parse(nextStartTime) - DateTime.Parse("00:00:00");
                var currEndTime = mediaFile1.Duration.TotalSeconds + timeSpan.TotalSeconds;
                if (currEndTime > timeSpanNext.TotalSeconds)
                {
                    var endTimeStr = DateTime.Parse("00:00:00").AddSeconds(currEndTime).ToString("HH:mm:ss");
                    throw new Exception($"the section [{sourceModel.Title}] media end time({endTimeStr}) is greater than next section[{listSourceFile[i + 1].Title}] start time({nextStartTime})");
                }
            }
            sbInputFile.Append($" -i {sourceModel.AudioFilePath}");
            //[0]adelay=1s:all=1[0a];
            //[1]adelay=26s:all=1[1a];
            //[0a][1a]
            sbAdelay.Append($"[{i}]adelay={startSeconds}s:all=1[{i}a];");
            strA += $"[{i}a]";
        }
        //param
        /*
            * ffmpeg -i 11.wav -i 13.wav -filter_complex \"[0]adelay=1s:all=1[0a];[1]adelay=26s:all=1[1a];[0a][1a]amix=inputs=2[a]\" 
            * -map \"[a]\" output11132.wav
            */
        string param = $"{sbInputFile} -filter_complex \"{sbAdelay}{strA}amix=inputs={listSourceFile.Count}[a]\" -map \"[a]\" {outputPath}";
        var conversion = FFmpeg.Conversions.New().AddStream(listStream).SetOutput(outputPath);
        var conversionResult = await conversion.Start(param);
        //return conversionResult.Duration;
    }
    
    internal class TextToSppechConversionModel
    {
        public string Title { get; set; }
        public string AudioFilePath { get; set; }
        public string StartTime { get; set; }
    }
    

    参考:
    //https://stackoverflow.com/questions/60027460/how-to-add-multiple-audio-files-at-specific-times-on-a-silence-audio-file-using
    //https://www.ffmpeg.org/ffmpeg-all.html#adelay
    //https://ffmpeg.org/ffmpeg-filters.html#amix
    //https://ffmpeg.xabe.net/docs.html
    //https://ffmpeg.xabe.net/tutorial.html

  • 相关阅读:
    TC SRM 591 (Div2. Practice only)
    SDL2 简单实现图片缩放移动查看
    Linux下socket编程 address already in use 问题
    POJ 2155 二维树状数组
    OJ开发笔记(1)
    开通博客啦~
    [转]STL transform算法中使用toupper函数
    Monkey and Banana HDU 1069
    Ignatius and the Princess IV HDU 1029
    Dungeon Master POJ 2251
  • 原文地址:https://www.cnblogs.com/grj1046/p/15611687.html
Copyright © 2020-2023  润新知