内容简介:音频是流式数据,并不像视频一样有P帧和B帧的概念。就像砌墙一样,咔咔往上摞就行了。一般来说,AAC编码中生成文件这一步,如果使用的是OutputStream流写入文件的话,就完全不需要计算时间。但在音视频同步或者使用Android自带的本文所涉及到的计算方法和API,为在Android环境下。使用AudioRecord音频录制,MediaCodeC编码AAC格式音频,同时使用MediaMuxer封装AAC格式音频文件。AAC编码有两种计算时间戳的方式。第一种:使用PCM的数据量来计算;第二种:计算出AAC编
音频是流式数据,并不像视频一样有P帧和B帧的概念。就像砌墙一样,咔咔往上摞就行了。一般来说,AAC编码中生成文件这一步,如果使用的是OutputStream流写入文件的话,就完全不需要计算时间。但在音视频同步或者使用Android自带的 MediaMuxer
来生成音频文件时,就需要计算音频帧的时间戳。
参考
本文所涉及到的计算方法和API,为在Android环境下。使用AudioRecord音频录制,MediaCodeC编码AAC格式音频,同时使用MediaMuxer封装AAC格式音频文件。
方法
AAC编码有两种计算时间戳的方式。第一种:使用PCM的数据量来计算;第二种:计算出AAC编码相应参数配置下,一帧的持续时间,再配合帧数来计算。
AAC编码、MediaMuxer生成文件伪代码
MediaCodeC的AAC编码流程不再赘述,这里用伪代码来代替。主要是为了体现在代码何处设置时间戳:
// MediaCodeC获得可用输入队列 index = codeC.dequeueInputBuffer(......) // 当获取到可用输出队列时,我们将获取的PCM数据填入 inputBuffer = codec.getInputBuffer(index) // 将PCM数据(ByteArray)填充到InputBuffer inputBuffer.put(byteAarray——PCM数据) codec.queueInputBuffer(index, 0, byteArray的size , presentationTimeUs, 0) 复制代码
在以上的伪代码中,presentationTimeUs就是需要我们设置时间戳的地方
填充PCM数据后,在得到MediaCodeC输出后,使用MedaMuxer写入数据,生成AAC文件。
path = 输出路径。后缀aac、或者mp4 mediaMuxer= MediaMuxer(path, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) mediaMuxer.addTrack(音频轨) mediaMuxer.start() // codec拿到可用的输出数据。这些数据就是AAC格式的音频数据 id = codec.dequeueOutputBuffer(bufferInfo, 10000) if(id >= 0){ outputBuffer = codec.getOutputBuffer(id) mediaMuxer.writeSamplet(audioTrack, outputBuffer, bufferInfo) } 复制代码
需要注意的是:使用MediaMuxer生成AAC音频文件时,不需要添加AAC头信息,直接写入即可。
MediaMuxer写入文件时,BufferInfo这个参数就包含了这一帧数据的偏移、以及时间戳等信息。
更加完整的音频编码代码,请参考GitHub地址 AudioEncoder
使用PCM的数据量来计算
PCM是没有经过压缩的纯音频数据,我之前写过一篇音频入门的文章初识音频,记录了一些PCM相关的常识问题,感兴趣的可以去看看。
PCM作为最原始的音频数据,可以根据大小来计算出时间,先给出公式:
presentationTimeUs = 1000000L * (totalBytes / 2) / sampleRate 复制代码
这是配置为采样率sampletRate、采样位数为16bit、单声道的PCM文件时间戳计算方式
接下来我们来分析以上公式的计算由来:
假设有一段PCM文件,采样率为 S
,采样位数为 n
--(一般 采样位数的选择有4bit、8bit、16bit、32bit),声道为单声道。那么在1s内,这段PCM的大小为:
size = S * n * 1,单位为bit 复制代码
众所周知, 1 Byte = 8bit
, 1 Short = 16bit
。那么单位时间内,PCM的大小为:
以byte为单位 = S * n * 1 / 8 以short为单位 = S * n * 1 / 16 复制代码
那么根据以上就可得到,配置参数为采样率sampleRate、16bit、声道为1的PCM文件,当传入编码器的总大小达到totalByte时,时间戳的计算方式:
currents (微妙) = totalByte / (sampleRate * 16 * 1 / 8) = totalByte / 2 / sampleRate * 1000000L 复制代码
当然如果选择以ShortArray来承载PCM数据的话,那么公式则变为:
currents (微妙) = totalShort / (sampleRate * 16 * 1 / 16) = totalShort / sampletRate * 1000000L 复制代码
使用AAC帧时间计算
当编码器每输出一次数据,即可视作输出一帧AAC数据。一帧AAC原始数据包括 1024
个sample,那么AAC音频文件1s内的帧数为: sampleRate / 1024 帧
。从而得到一帧AAC的持续时间为:
perFrameTime (微妙) = 1000000L / sampleRate / 1024 复制代码
已知每一帧的持续时间的话,那么只需要根据当前帧数,即可计算出当前的时间戳。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 音频编码 Audio Converter
- php base64 编码图片,音频,视频
- 音视频入门之音频采集、编码、播放
- LameXP v4.16 发布,多用途音频编码器
- PCM 编码与 Waveform 音频文件 (.wav) 格式详解
- PCM 编码与 Waveform 音频文件 (.wav) 格式详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。