双声道MP4转独立单声道WAV:FFmpeg/Python解决方案求助
我是音频编码领域新手,想把双声道MP4文件拆成两个独立的单声道WAV文件,每个文件对应一个麦克风采集的音频,方便后续转文本并按声道标记说话人。但用FFmpeg命令和Python代码尝试后,两个文件内容完全一致。附上ffprobe检测结果、之前试的命令和代码,求正确的FFmpeg命令或Python脚本。
FFprobe检测信息
使用的命令:
ffprobe -i Two-Channel.mp4 -show_streams -select_streams a
检测结果:
Metadata: major_brand : mp42 minor_version : 0 compatible_brands: isommp42 encoder : Google Duration: 00:52:42.19, start: 0.000000, bitrate: 421 kb/s Stream #0:0[0x1](und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 640x360 [SAR 1:1 DAR 16:9], 322 kb/s, 25 fps, 25 tbr, 12800 tbn (default) Metadata: handler_name : ISO Media file produced by Google Inc. vendor_id : [0][0][0][0] Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 96 kb/s (default) Metadata: handler_name : ISO Media file produced by Google Inc. vendor_id : [0][0][0][0] [STREAM] index=1 codec_name=aac codec_long_name=AAC (Advanced Audio Coding) profile=LC codec_type=audio codec_tag_string=mp4a codec_tag=0x6134706d sample_fmt=fltp sample_rate=44100 channels=2 channel_layout=stereo bits_per_sample=0 initial_padding=0 id=0x2 r_frame_rate=0/0 avg_frame_rate=0/0 time_base=1/44100 start_pts=0 start_time=0.000000 duration_ts=139452416 duration=3162.186304 bit_rate=96000 max_bit_rate=N/A bits_per_raw_sample=N/A nb_frames=136184 nb_read_frames=N/A nb_read_packets=N/A extradata_size=16 DISPOSITION:default=1 DISPOSITION:dub=0 DISPOSITION:original=0 DISPOSITION:comment=0 DISPOSITION:lyrics=0 DISPOSITION:karaoke=0 DISPOSITION:forced=0 DISPOSITION:hearing_impaired=0 DISPOSITION:visual_impaired=0 DISPOSITION:clean_effects=0 DISPOSITION:attached_pic=0 DISPOSITION:timed_thumbnails=0 DISPOSITION:non_diegetic=0 DISPOSITION:captions=0 DISPOSITION:descriptions=0 DISPOSITION:metadata=0 DISPOSITION:dependent=0 DISPOSITION:still_image=0 TAG:language=eng TAG:handler_name=ISO Media file produced by Google Inc. TAG:vendor_id=[0][0][0][0] [/STREAM]
此前尝试的FFmpeg命令
ffmpeg -i Two-Channel.mp4 -filter_complex "pan=mono|c0=0c0" left_channel.wav
此前尝试的Python代码
先通过FFmpeg将MP4转为WAV,之后用Python处理(原代码核心逻辑是读取WAV文件后尝试提取左右声道,但最终输出的两个文件内容完全一致)
正确的解决方案
方案1:直接用FFmpeg拆分声道
提取左声道:
ffmpeg -i Two-Channel.mp4 -map_channel 0.1.0 left_channel.wav
提取右声道:
ffmpeg -i Two-Channel.mp4 -map_channel 0.1.1 right_channel.wav
或者用channelsplit滤镜一次性输出两个文件,效率更高:ffmpeg -i Two-Channel.mp4 -filter_complex "channelsplit=channel_layout=stereo[left][right]" -map "[left]" left.wav -map "[right]" right.wav
方案2:Python脚本(使用pydub库,简单易用)
先安装依赖:pip install pydub
脚本代码:
from pydub import AudioSegment # 加载MP4文件(需确保FFmpeg已添加到系统环境变量) audio = AudioSegment.from_file("Two-Channel.mp4", format="mp4") # 拆分左右声道 left_channel = audio.split_to_mono()[0] right_channel = audio.split_to_mono()[1] # 保存为单声道WAV文件 left_channel.export("left_channel.wav", format="wav") right_channel.export("right_channel.wav", format="wav")
方案3:Python脚本(使用标准库,无需第三方依赖)
先通过FFmpeg将MP4转为PCM编码的WAV(避免编码问题):ffmpeg -i Two-Channel.mp4 -acodec pcm_s16le -ar 44100 -ac 2 temp.wav
然后用标准库wave和struct处理:
import wave import struct with wave.open("temp.wav", "rb") as wav_file: params = wav_file.getparams() nchannels, sampwidth, framerate, nframes = params[:4] # 读取所有音频帧 frames = wav_file.readframes(nframes) # 将二进制帧转成整数数组 fmt = "<h" * nframes * nchannels samples = struct.unpack(fmt, frames) # 拆分左右声道:左声道取偶数索引,右声道取奇数索引 left_samples = samples[0::2] right_samples = samples[1::2] # 保存左声道WAV with wave.open("left_channel.wav", "wb") as left_wav: left_wav.setparams((1, sampwidth, framerate, nframes, params.compname, params.descrip)) left_frames = struct.pack("<h" * len(left_samples), *left_samples) left_wav.writeframes(left_frames) # 保存右声道WAV with wave.open("right_channel.wav", "wb") as right_wav: right_wav.setparams((1, sampwidth, framerate, nframes, params.compname, params.descrip)) right_frames = struct.pack("<h" * len(right_samples), *right_samples) right_wav.writeframes(right_frames)
内容的提问来源于stack exchange,提问作者Harish Alwala

