iOS 支持音視頻倍速播放
基于使用ffmpeg+AudioUnit+OpenGL的一個視頻播放器實現倍速播放功能:
用ffmpeg解碼出得到PCM格式的音頻數據,由AudioUnit播放音頻,在播放之前通過sonic庫轉化為所需倍速的PCM格式音頻
sonic是一個C++庫,用法簡單無需添加依賴庫, 直接傳入的是PCM格式,輸出的也是PCM格式,這樣的用起來很方便,不需要格式轉換
sonic的關鍵代碼
1.創建一個stream流,并設置相關參數
stream=sonicCreateStream((int)(sampleRate), (int)(channels));
sonicSetSpeed(stream, 1.0);//通過設置speed來實現倍速播放(聲音不會變調)
sonicSetPitch(stream, 1.0);
sonicSetVolume(stream, 1.0);
sonicSetRate(stream, 1.0);//通過設置rate來實現倍速(聲音會變調)
2、相關的轉換代碼
- (NSData *)setFloatData:(NSData *)data{
NSMutableData *sonicdDatas = [[NSMutableData alloc] init];
int lenBytes = (int)data.length;
float * dataBytes = (float *)[data bytes];
float * outBytes = (float *)malloc(lenBytes);
int samples = lenBytes/(sizeof(float)* sonicGetNumChannels(stream));
//傳入數據,注意數據類型如果是short類型用 sonicWriteShortToStream(stream, dataBytes, samples),否則轉換后聲音會出現呲呲的噪音
int ret = sonicWriteFloatToStream(stream, dataBytes, samples);
if (ret) {
int available = sonicSamplesAvailable(stream) * sizeof(float) * sonicGetNumChannels(stream);
if (lenBytes > available) {
lenBytes = available;
}
outBytes = (float *)realloc(outBytes, lenBytes);
int samplesRead;
do {
samplesRead = sonicReadFloatFromStream(stream, outBytes, lenBytes/(sizeof(float)*sonicGetNumChannels(stream)));
if (samplesRead > 0) {
int bytesRead = samplesRead * sizeof(float) * sonicGetNumChannels(stream);
[sonicdDatas appendBytes:outBytes length:bytesRead];
}
} while (samplesRead > 0);
}
free(outBytes);
return sonicdDatas; //返回轉換后的數據
}
3.通過改變speed的值來實現倍速播放
-(void)setPlaySpeed:(double)playSpeed{
_playSpeed = playSpeed;
sonicSetSpeed(stream, playSpeed);
}
當音頻可倍速播放之后,可以音頻的時間為軸來控制視頻幀的渲染速度,進而達到音視頻同步播放的效果。