用ffmpeg批量转换WAV文件采样率

问题由来:有一批客服提供的配音文件,好几千个,需要用作我写的程序合成,发现其尺寸差异较大,遂检查了一遍,发现果然里面10%的文件格式有问题,和其他不一致:

Option Explicit

Public Type RIFF
    ID As String * 4    '0x00    4Byte   大端    'RIFF' (0x52494646)
    Size As Long        '0x04    4Byte   小端    fileSize - 8
    Type As String * 4  '0x08    4Byte   大端    'WAVE'(0x57415645)
End Type

Public Type FORMAT
    ID As String * 4        '   0x00    4Byte   大端    'fmt ' (0x666D7420)
    Size  As Long           '   0x04    4Byte   小端    16
    AudioFormat As Integer  '   0x08    2Byte   小端    音频格式
    NumChannels As Integer  '   0x0A    2Byte   小端    声道数
    SampleRate As Long      '   0x0C    4Byte   小端    采样率
    ByteRate As Long        '   0x10    4Byte   小端    每秒数据字节数
    BlockAlign As Integer   '   0x14    2Byte   小端    数据块对齐
    BitsPerSample As Integer '  0x16    2Byte   小端    采样位数
End Type

Public Type data
    ID As String * 4    ' 0x00    4Byte   大端    'data' (0x64617461)
    Size As Long        ' 0x04    4Byte   小端    N
    dataBlock() As Integer
End Type

Public Type HP1
    data As String * 14    '0x00    4Byte   大端    Lavf58.29.100
End Type

Public Type HP
    ID As String * 8    '0x00    4Byte   大端    INFOISFT
    Size As Long        '0x04    4Byte   小端
    data As HP1
End Type

Public Type LIST '-------------ffmpeg 转换出来的 WAV 文件,文件头会多出 LIST 块,所以单独定义个判断下,以免忘记了。
    ID As String * 4    '0x00    4Byte   大端    LIST
    Size As Long        '0x04    4Byte   小端
    data As HP
End Type

Public Function apppath()
    apppath = ActiveWorkbook.Path & "\"
End Function

Public Sub chkWavFormat()
    Dim P1 As RIFF, P2 As FORMAT, P3 As data, P2x As LIST
    Dim P0 As RIFF, AR As Long, dataBlock() As Integer
    Dim i As Integer, fn As String, fpath As String, fp As Integer, col As Integer
    Dim Headsize As Long
    
    fpath = apppath & "基本语音\wav\"
    fn = Dir(fpath & "*.wav")
    Do
        '-----------读取文件格式
        fp = FreeFile
        Open fpath & fn For Binary As #fp
            Get #fp, , P1
            Get #fp, , P2
            Get #fp, , P0
            AR = Seek(fp) - 12
            Seek #fp, AR
            If P0.ID <> "data" Then
                Get #fp, , P2x
                Headsize = 12 + 8 + P2.Size + 8 + P2x.Size + 8
            Else
                Headsize = 12 + 8 + P2.Size + 8
            End If
'            Get #fp, , P3.ID
'            Get #fp, , P3.Size
            If P2.BlockAlign = 1 Then
                'ReDim dataBlock(1 To P3.Size) As Byte
            ElseIf P2.BlockAlign = 2 Then
                'ReDim dataBlock(1 To P3.Size / 2) As Integer
            Else
'                Close #fp
'                MsgBox "不处理32位音频!"
'                Exit Sub
            End If
        Close #fp
        
        '------------------
        i = i + 1
        col = 1
        Worksheets("Sheet3").Cells(10 + i, col).Value = i: col = col + 1
        Worksheets("Sheet3").Cells(10 + i, col).Value = fn: col = col + 1
        With P2
            Worksheets("Sheet3").Cells(10 + i, col).Value = .AudioFormat: col = col + 1
            Worksheets("Sheet3").Cells(10 + i, col).Value = .NumChannels: col = col + 1
            Worksheets("Sheet3").Cells(10 + i, col).Value = .SampleRate: col = col + 1
            Worksheets("Sheet3").Cells(10 + i, col).Value = .ByteRate: col = col + 1
            Worksheets("Sheet3").Cells(10 + i, col).Value = .BlockAlign: col = col + 1
            Worksheets("Sheet3").Cells(10 + i, col).Value = .BitsPerSample: col = col + 1
        End With
        Worksheets("Sheet3").Cells(10 + i, col).Value = Headsize: col = col + 1
        '——----------
        DoEvents
        fn = Dir
    Loop Until Len(fn) < 4
    MsgBox i & "个文件处理完毕"
End Sub

而且发现所有文件采样率和我程序要求的都不一样。

所以想将其格式全部转换为我设定的一致,用 ffpmeg 试了一下,发现直接 wav 转 wav 转出来得到是 PCM 格式文件,并不能得到 wav 格式文件:

ffmpeg -y -i 12.wav -f s16le -ac 1 -ar 16000 -acodec pcm_s16le 12.ok.wav

 图中可将,wav 文件头没了,将扩展名改为 PCM 用 goldwave 打开,填入之前转换的参数,播放正确:

 

 说明格式采样率转换已经正确完成,只是 ffpmeg 只输出了数据部分,没带 wav 文件头,那么接下来就简单了,从 pcm 转为 wav 加上文件头,就可以得到完整的 wav 文件了:

ffmpeg -y -f s16le -ac 1 -ar 16000 -acodec pcm_s16le -i 12.ok.pcm test.wav

至此,转换方案可以确定,即,将各种不同格式的 wav 文件先转为 16位16K单声 pcm 格式,然后,在按这个格式转换为 wav 格式即可,加上批处理批量转换两次就完成了:

rem 不同格式的 wav 文件批量转换为 16 位 16K 单声道的 pcm 格式
e:
cd E:\Studio\web\xfttsWeb\DOC\基本语音
for %%a in (".\all\*.wav") do "ffmpeg.exe" -y -i "%%a" -f s16le -ac 1 -ar 16000 -acodec pcm_s16le ".\pcm\%%~na.pcm"
rem pcm 文件批量转换为 16 位 16K 单声道的 wav 格式
e:
cd E:\Studio\web\xfttsWeb\DOC\基本语音
for %%a in (".\pcm\*.pcm") do "ffmpeg.exe" -y -f s16le -ac 1 -ar 16000 -acodec pcm_s16le -i "%%a" ".\wav\%%~na.wav"

这样,几分钟就把一堆不同采样率的文件一起转换好了。

转换后的文件再次检测格式,都已经全部为制定格式:

此记!

ps:ffmpg 转换 wav 文件采样率时,不能直接转为 wav 格式,需要用 pcm 格式过渡一次。

猜你喜欢

转载自blog.csdn.net/jessezappy/article/details/121019277