如何将WebRTC采集的PCMA音频保存至磁盘?
如何将音频保存为PCMA格式?
问题核心
你遇到的问题是OGG容器不兼容PCMA(G.711 A律)音频流——OGG通常用于封装Opus、Vorbis这类编码,直接将PCMA数据写入OGG文件会导致格式混乱,播放器无法解析。
PCMA属于原始音频编码,有两种可靠的保存方式:直接保存为PCMA裸流文件(后缀.pcm),或者封装为WAV容器文件(后缀.wav,兼容性更强,多数播放器可直接识别)。
代码调整方案
1. 修改Track回调逻辑
替换原OGG保存逻辑,改为保存PCMA裸流或WAV文件:
peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) { codec := track.Codec() fmt.Println(codec.MimeType) if strings.EqualFold(codec.MimeType, webrtc.MimeTypePCMA) { fmt.Println("Got PCMA track, saving to disk as output.pcm (8 kHz, 1 channel)") // 方式1:保存为原始PCMA裸流 saveRawPCMA("output.pcm", track) // 方式2:保存为WAV文件(推荐,无需额外转换即可播放) // savePCMAAsWAV("output.wav", track) } })
2. 实现PCMA裸流保存函数
直接将RTP payload中的PCMA原始数据写入文件:
import "os" func saveRawPCMA(filePath string, track *webrtc.TrackRemote) { file, err := os.Create(filePath) if err != nil { panic(err) } defer file.Close() buf := make([]byte, 1500) for { n, _, err := track.Read(buf) if err != nil { return } // 直接写入PCMA原始数据 if _, err := file.Write(buf[:n]); err != nil { panic(err) } } }
3. (可选)封装为WAV文件
给PCMA数据加上WAV头,让播放器直接识别:
import ( "encoding/binary" "os" ) func savePCMAAsWAV(filePath string, track *webrtc.TrackRemote) { file, err := os.Create(filePath) if err != nil { panic(err) } defer file.Close() // WAV文件头结构,适配PCMA编码(8kHz采样率、单声道、8位A律) var wavHeader = struct { ChunkID [4]byte ChunkSize uint32 Format [4]byte Subchunk1ID [4]byte Subchunk1Size uint32 AudioFormat uint16 // 6代表PCMA编码 NumChannels uint16 SampleRate uint32 ByteRate uint32 BlockAlign uint16 BitsPerSample uint16 Subchunk2ID [4]byte Subchunk2Size uint32 }{ ChunkID: [4]byte{'R', 'I', 'F', 'F'}, Format: [4]byte{'W', 'A', 'V', 'E'}, Subchunk1ID: [4]byte{'f', 'm', 't', ' '}, Subchunk1Size: 16, AudioFormat: 6, NumChannels: 1, SampleRate: 8000, ByteRate: 8000 * 1, // 采样率×声道数(PCMA每个采样占1字节) BlockAlign: 1, BitsPerSample: 8, Subchunk2ID: [4]byte{'d', 'a', 't', 'a'}, } // 先写入初始头(后续更新数据大小) if err := binary.Write(file, binary.LittleEndian, wavHeader); err != nil { panic(err) } buf := make([]byte, 1500) dataSize := uint32(0) for { n, _, err := track.Read(buf) if err != nil { break } if _, err := file.Write(buf[:n]); err != nil { panic(err) } dataSize += uint32(n) } // 更新头中的大小字段 wavHeader.ChunkSize = 36 + dataSize wavHeader.Subchunk2Size = dataSize if _, err := file.Seek(0, 0); err != nil { panic(err) } if err := binary.Write(file, binary.LittleEndian, wavHeader); err != nil { panic(err) } }
验证方法
- 若保存为
.pcm文件:可通过ffmpeg转换为WAV播放,命令如下:ffmpeg -f alaw -ar 8000 -ac 1 -i output.pcm output.wav - 若保存为
.wav文件:直接用系统默认播放器打开即可。
内容的提问来源于stack exchange,提问作者user22950238
相关产品推荐
相关产品推荐

