ReplayKit2 采集音视频回调格式分析
一、iOS中的音视频都是采用一个叫做CMSampleBuffer的格式封装的
比如回调的App音频
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | Printing description of sampleBuffer: CMSampleBuffer 0x143d06560 retainCount: 1 allocator: 0x25bae95e0 invalid = NO dataReady = YES makeDataReadyCallback = 0x0 makeDataReadyRefcon = 0x0 formatDescription = <CMAudioFormatDescription 0x281940990 [0x25bae95e0]> { mediaType: 'soun' mediaSubType: 'lpcm' mediaSpecific: { ASBD: { mSampleRate: 44100.000000 mFormatID: 'lpcm' mFormatFlags: 0xe mBytesPerPacket: 2 mFramesPerPacket: 1 mBytesPerFrame: 2 mChannelsPerFrame: 1 mBitsPerChannel: 16 } cookie: {(null)} ACL: {(null)} FormatList Array: {(null)} } extensions: {(null)} } sbufToTrackReadiness = 0x0 numSamples = 22528 sampleTimingArray[1] = { {PTS = {619877934457375/1000000000 = 619877.934}, DTS = {INVALID}, duration = {1/44100 = 0.000}}, } dataBuffer = 0x281940360 |
比如回调的micphone音频
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | Printing description of sampleBuffer: CMSampleBuffer 0x149e053b0 retainCount: 1 allocator: 0x25bae95e0 invalid = NO dataReady = YES makeDataReadyCallback = 0x0 makeDataReadyRefcon = 0x0 formatDescription = <CMAudioFormatDescription 0x281b47b10 [0x25bae95e0]> { mediaType: 'soun' mediaSubType: 'lpcm' mediaSpecific: { ASBD: { mSampleRate: 44100.000000 mFormatID: 'lpcm' mFormatFlags: 0xc mBytesPerPacket: 2 mFramesPerPacket: 1 mBytesPerFrame: 2 mChannelsPerFrame: 1 mBitsPerChannel: 16 } cookie: {(null)} ACL: {(null)} FormatList Array: {(null)} } extensions: {(null)} } sbufToTrackReadiness = 0x0 numSamples = 1024 sampleTimingArray[1] = { {PTS = {27273930501/44100 = 618456.474, rounded}, DTS = {INVALID}, duration = {1/44100 = 0.000}}, } dataBuffer = 0x281b47c30 |
从这个结构中,可以得到这个音频数据的描述信息
1 2 3 4 5 6 7 8 9 10 | // Get samples. CMBlockBufferRef audioBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); size_t lengthAtOffset; size_t totalLength; char *samples; CMBlockBufferGetDataPointer(audioBuffer, 0, &lengthAtOffset, &totalLength, &samples); // Get format. CMAudioFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer); const AudioStreamBasicDescription *description = CMAudioFormatDescriptionGetStreamBasicDescription(format); |
输出为格式的描述信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Printing description of format: <CMAudioFormatDescription 0x28282f7b0 [0x25bae95e0]> { mediaType: 'soun' mediaSubType: 'lpcm' mediaSpecific: { ASBD: { mSampleRate: 44100.000000 mFormatID: 'lpcm' mFormatFlags: 0xc mBytesPerPacket: 2 mFramesPerPacket: 1 mBytesPerFrame: 2 mChannelsPerFrame: 1 mBitsPerChannel: 16 } cookie: {(null)} ACL: {(null)} FormatList Array: {(null)} } extensions: {(null)} } |
关于音频格式有几个关键信息:格式、采样率、采样精度、声道数
关于音频数据除了上面的格式信息之外,还有 PTS 、 samples(帧数)描述信息
比如上面的PCM数据中,采样率是44100hz、采样深度是16位、声道数是1,samples是1024帧,最后计算这段声音的长度信息是 (1/44100) * 1024 = 23ms , 这个声音的数据大小是 1024 * 2byte = 2014 Byte
如果是录制声音的话,需要先设置需要录制的音频格式信息
1 2 3 4 5 6 7 8 9 10 | AudioStreamBasicDescription format; memset(&format, 0, sizeof (format)); format.mSampleRate = 44100; format.mFormatID = kAudioFormatLinearPCM; format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; format.mChannelsPerFrame = 1; format.mBitsPerChannel = 16; format.mBytesPerFrame = (format.mBitsPerChannel/8) * format.mChannelsPerFrame; format.mFramesPerPacket = 1; format.mBytesPerPacket = format.mBytesPerFrame * format.mFramesPerPacket; |
需要设置关键参数、采样率、采样精度、声道数、数据排列格式、 一个packet的帧数
附录:
关于采样精度
关于采样率
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2014-11-05 IOS真机Profile时调用树中的对象只是显示地址,没有显示symbol name