2020-07-23

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);
 }

當音頻可倍速播放之后,可以音頻的時間為軸來控制視頻幀的渲染速度,進而達到音視頻同步播放的效果。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。