如宣传片、TVC、自媒体、短视频,或者口播信息流等,这些视频通常都需要额外配音,尤其是真人配音,很多时候配音者控制不好速度和间隔,如果对视频质量有要求的话,剪辑师要花不少时间去预剪辑配音音频,来平衡统一气口间隙。

当然现在也有不少软件可以自动剪辑,比如剪映这类大众化剪辑工具,甚至直接内置了此类功能,不过需要付费VIP才能使用。而剪映工作流也并不适用于很多高端专业领域的剪辑工作,所以,开发一个独立软件来预处理音频剪辑,就非常有必要了。

花了2小时开发软件核心,然后又花了两天修复各种bug,现在总算是成熟完工了。

支持导入视频或音频,软件会自动分析处理波形总的空隙区域,然后点击导出按钮就完成了。

需要注意的是,最好导入音频文件,导入视频好像容易卡死。以及,1小时以上的超长音频似乎也容易卡死。

下载软件

使用教程:
1.点击打开第一栏右边的[打开按钮],选择要处理的音频或视频文件。最好提前转音频,导入视频容易卡死。
2.软件会自动点击[处理]按钮,如果你修改了下面的参数,则需要再手动点击处理按钮。
3.导出,完成。文件将会导出到原文件同目录,名字开头为 mcc_

补充说明:
本软件完全免费
目前只有 Windows 版本


(以下是专业向内容)

软件使用VB.net4.8 WPF开发,使用Win-UI库实现Win11的UI效果,调用FFmpeg.exe实现媒体处理,最后使用canvas控件绘制音频频谱。

1.读取音频波形

  Public Function GetAudioWaveform(filePath As String, sampleRate As Integer) As List(Of Single)
 
        Dim waveformData As New List(Of Single)()
 
        Using ffmpegProcess As New Process()
              ' 设置进程启动信息
              Dim startInfo As New ProcessStartInfo()
              startInfo.FileName = "D:\ffmpeg\ffmpeg.exe"
              startInfo.UseShellExecute = False
              startInfo.RedirectStandardOutput = True
              startInfo.RedirectStandardError = True
              startInfo.CreateNoWindow = True
 
              ' 构建FFmpeg命令行参数
              ' -i: 输入文件路径
              ' -vn: 禁用视频流
              ' -f f32le: 输出32位浮点小端格式
              ' -ar: 音频采样率
              ' -ac 1: 单声道输出
              ' pipe:1: 输出到标准输出
              startInfo.Arguments = $"-i ""{filePath}"" -vn -f f32le -ar {sampleRate} -ac 1 pipe:1"
 
              ffmpegProcess.StartInfo = startInfo
 
              Try
                    ffmpegProcess.Start()
 
                    Using outputStream As Stream = ffmpegProcess.StandardOutput.BaseStream
                          Dim buffer(3) As Byte
 
                          While (outputStream.Read(buffer, 0, 4) = 4)
                                Dim sample As Single = BitConverter.ToSingle(buffer, 0)
                                waveformData.Add(sample)
                                ProcessBarAdd()
                          End While
                    End Using
 
                    ' 等待进程完成
                    ffmpegProcess.WaitForExit()
 
              Catch ex As Exception
                    Console.WriteLine($"获取音频波形时出错: {ex.Message}")
                    Return New List(Of Single)()
              End Try
        End Using
 
        Return waveformData
  End Function

通过以上函数,即可调用 ffmpeg.exe 读取音频波形,并返回为 list(of single) 类型的数据列表。

需要注意的是,以上代码没有加入异步事件,并且读取时会将采样范围的所有数据列入list中,这种操作对性能是有一定局限性的,正如上面介绍软件时所说,本软件处理1小时以上的音频时容易卡死,就是因为这个原因。只是考虑到1小时以上的超长剪辑需求过于刁钻,基本用不到,就不考虑优化了。

如果需要优化这个问题,比如可以多分几个list,每个list只读取1000万个浮点这样,应该可以大幅优化,但也会增加一些代码复杂度。

2.将波形浮点转为音量分贝数

 Public Function SampleToDecibel(sample As Single) As Single
       Const MIN_DB As Single = -96.0F   ' 最小分贝值 (静音阈值)
       Const MAX_DB As Single = 0.0F     ' 最大分贝值 (0dBFS)
 
       Dim amplitude As Single = Math.Abs(sample)
 
       If amplitude < Single.Epsilon Then
             Return MIN_DB  ' 完全静音
       End If
 
       ' 计算分贝值:20 * log10(amplitude)
       Dim db As Single = 20.0F * CSng(Math.Log10(amplitude))
 
       Return Math.Min(Math.Max(db, MIN_DB), MAX_DB)
 End Function

3.对比波形音量

我的实现方式是直接for each 整个 list,这种方法简单粗暴,缺点是性能较差,速度有点慢,处理10分钟音频文件大概需要7、8秒,也能接受罢了。

这里可以优化为,每1万个波形点对比一次,如果对比时发现音量有大幅度变化,再回到上一个对比点,把这1万个波形点逐个对比,用这种粗对比+细对比组合的方式,应该能将速度直接提升个5~10倍。

4.调用ffmpeg处理

这块就不多说了,比较麻烦……建议问 AI

5.绘制音频波形

  Private Sub DrawWave()
        CanvasWave.Children.Clear()
        Dim xxx As Double = 0
        Dim screenX As Double = Me.Width
        Dim forStep As Integer = Math.Round(waveDataSingle.Count / screenX)
        Dim lineHeight As Double = 90
        For i As Integer = 0 To waveDataSingle.Count - 1 Step forStep / 1.76
              xxx += 0.5
              Dim source As Single = waveDataSingle(i)
              Dim volumeDB As Single = Math.Abs(SampleToDecibel(source))
              volumeDB = Math.Min(lineHeight, Math.Max(0, lineHeight * Math.Pow(volumeDB / lineHeight, 0.6F))) ' 0.6F 是幂函数压缩指数,越小压缩越强
 
              DrawHorizontalLine(xxx, lineHeight, xxx, volumeDB, CheckClipListState(i))
        Next
  End Sub
 
  Private Sub DrawHorizontalLine(x1 As Double, y1 As Double, x2 As Double, y2 As Double, Optional type As Integer = 0)
        Dim line As New Line()
 
        line.X1 = x1
        line.Y1 = y1
        line.X2 = x2
        line.Y2 = y2
 
        ' 设置线条样式
        Dim colorCode As String = "908da6"
        Dim color As Color = CType(ColorConverter.ConvertFromString($"#{colorCode}"), Color)
        If type = 1 Then
              color = CType(ColorConverter.ConvertFromString($"#DC3545"), Color)
        End If
 
        line.Stroke = New SolidColorBrush(color)
        line.StrokeThickness = 0.65
 
        ' 添加到Canvas
        CanvasWave.Children.Add(line)
  End Sub

直接封装了一个 DrawWave() 方法,调用后,会直接for each 读取整个音频浮点列表。不过这里做了优化,即并不会将所有浮点绘制出来,那样绘制出来了也显示不了那么精细的波形,而且速度还很慢。我的做法是,通过检测窗口的宽度像素来决定for循环的step步幅,以实现只绘制窗口需要的像素量,窗口撑死几百像素宽度,因此这部分工作几乎是瞬间完成。

非常有意思的小工具。


CSDN原文 (也是我)