如宣传片、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原文 (也是我)