在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    FFmpeg音視頻同步

    FFmpeg音視頻同步

    視頻同步在音視頻開發(fā)中是非常重要的知識點(diǎn),所以在這里記錄下音視頻同步相關(guān)知識的理解。

    音視頻同步簡介

    從前面的學(xué)習(xí)可以知道,在一個視頻文件中,音頻和視頻都是單獨(dú)以一條流的形式存在,互不干擾。那么在播放時根據(jù)視頻的幀率(Frame Rate)和音頻的采樣率(Sample Rate)通過簡單的計算得到其在某一Frame(Sample)的播放時間分別播放,**理論**上應(yīng)該是同步的。但是由于機(jī)器運(yùn)行速度,解碼效率等等因素影響,很有可能出現(xiàn)音頻和視頻不同步,例如出現(xiàn)視頻中人在說話,卻只能看到人物嘴動卻沒有聲音,非常影響用戶觀看體驗(yàn)。

    如何做到音視頻同步?要知道音視頻同步是一個動態(tài)的過程,同步是暫時的,不同步才是常態(tài),需要一種隨著時間會線性增長的量,視頻和音頻的播放速度都以該量為標(biāo)準(zhǔn),播放快了就減慢播放速度;播放慢了就加快播放的速度,在你追我趕中達(dá)到同步的狀態(tài)。目前主要有三種方式實(shí)現(xiàn)同步:

    • 將視頻和音頻同步外部的時鐘上,選擇一個外部時鐘為基準(zhǔn),視頻和音頻的播放速度都以該時鐘為標(biāo)準(zhǔn)。
    • 將音頻同步到視頻上,就是以視頻的播放速度為基準(zhǔn)來同步音頻。
    • 將視頻同步到音頻上,就是以音頻的播放速度為基準(zhǔn)來同步視頻。

    比較主流的是第三種,將視頻同步到音頻上。至于為什么不使用前兩種,因?yàn)橐话銇碚f,人對于聲音的敏感度更高,如果頻繁地去調(diào)整音頻會產(chǎn)生雜音讓人感覺到刺耳不舒服,而人對圖像的敏感度就低很多了,所以一般都會采用第三種方式。

    復(fù)習(xí)DTS、PTS和時間基

    • PTS: Presentation Time Stamp,顯示渲染用的時間戳,告訴我們什么時候需要顯示
    • DTS: Decode Time Stamp,視頻解碼時的時間戳,告訴我們什么時候需要解碼

    在音頻中PTS和DTS一般相同。但是在視頻中,由于B幀的存在,PTS和DTS可能會不同。

    實(shí)際幀順序:I B B P

    存放幀順序:I P B B

    解碼時間戳:1 4 2 3

    展示時間戳:1 2 3 4

    • 時間基

    /** * This is the fundamental unit of time (in seconds) in terms * of which frame timestamps are represented. * 這是表示幀時間戳的基本時間單位(以秒為單位)。**/typedef struct AVRational{ int num; ///< Numerator 分子 int den; ///< Denominator 分母} AVRational;

    時間基是一個分?jǐn)?shù),以秒為單位,比如1/50秒,那它到底表示的是什么意思呢?以幀率為例,如果它的時間基是1/50秒,那么就表示每隔1/50秒顯示一幀數(shù)據(jù),也就是每1秒顯示50幀,幀率為50FPS。

    每一幀數(shù)據(jù)都有對應(yīng)的PTS,在播放視頻或音頻的時候我們需要將PTS時間戳轉(zhuǎn)化為以秒為單位的時間,用來最后的展示。那如何計算一楨在整個視頻中的時間位置?

    static inline double av_q2d(AVRational a){ return a.num / (double) a.den;}//計算一楨在整個視頻中的時間位置timestamp(秒) = pts * av_q2d(st->time_base);

    Audio_Clock

    Audio_Clock,也就是Audio的播放時長,從開始到當(dāng)前的時間。獲取Audio_Clock:

    if (pkt->pts != AV_NOPTS_VALUE) { state->audio_clock = av_q2d(state->audio_st->time_base) * pkt->pts;}

    【免費(fèi)分享】整理了一些學(xué)習(xí)資料、教學(xué)視頻和學(xué)習(xí)路線圖,資料包括《Andoird音視頻開發(fā)必備手冊+音視頻學(xué)習(xí)視頻+學(xué)習(xí)文檔資料包+大廠面試真題+2022最新學(xué)習(xí)路線圖》等

    點(diǎn)擊下方鏈接加衛(wèi)星號獲取,領(lǐng)取資料一定要備注來源:“007”,會優(yōu)先通過

    FFmpegWebRTCRTMPRTSPHLSRTP播放器-音視頻流媒體高級開發(fā)

    還沒有結(jié)束,由于一個packet中可以包含多個Frame幀,packet中的PTS比真正的播放的PTS可能會早很多,可以根據(jù)Sample Rate 和 Sample Format來計算出該packet中的數(shù)據(jù)可以播放的時長,再次更新Audio_Clock。

    // 每秒鐘音頻播放的字節(jié)數(shù) 采樣率 * 通道數(shù) * 采樣位數(shù) (一個sample占用的字節(jié)數(shù))n = 2 * state->audio_ctx->channels;state->audio_clock += (double) data_size / (double) (n * state->audio_ctx->sample_rate);

    最后還有一步,在我們獲取這個Audio_Clock時,很有可能音頻緩沖區(qū)還有沒有播放結(jié)束的數(shù)據(jù),也就是有一部分?jǐn)?shù)據(jù)實(shí)際還沒有播放,所以就要在Audio_Clock上減去這部分?jǐn)?shù)據(jù)的播放時間,才是真正的Audio_Clock。

    double get_audio_clock(VideoState *state) { double pts; int buf_size, bytes_per_sec; //上一步獲取的PTS pts = state->audio_clock; // 音頻緩沖區(qū)還沒有播放的數(shù)據(jù) buf_size = state->audio_buf_size – state->audio_buf_index; // 每秒鐘音頻播放的字節(jié)數(shù) bytes_per_sec = state->audio_ctx->sample_rate * state->audio_ctx->channels * 2; pts -= (double) buf_size / bytes_per_sec; return pts;}

    get_audio_clock中返回的才是我們最終需要的Audio_Clock,當(dāng)前的音頻的播放時長。

    Video_Clock

    Video_Clock,視頻播放到當(dāng)前幀時的已播放的時間長度。

    avcodec_send_packet(state->video_ctx, packet);while (avcodec_receive_frame(state->video_ctx, pFrame) == 0) { if ((pts = pFrame->best_effort_timestamp) != AV_NOPTS_VALUE) { } else { pts = 0; } pts *= av_q2d(state->video_st->time_base); // 時間基換算,單位為秒 pts = synchronize_video(state, pFrame, pts); av_packet_unref(packet);}

    舊版的FFmpeg使用av_frame_get_best_effort_timestamp函數(shù)獲取視頻的最合適PTS,新版本的則在解碼時生成了best_effort_timestamp。但是依然可能會獲取不到正確的PTS,所以在synchronize_video中進(jìn)行處理。

    double synchronize_video(VideoState *state, AVFrame *src_frame, double pts) { double frame_delay; if (pts != 0) { state->video_clock = pts; } else { pts = state->video_clock;// PTS錯誤,使用上一次的PTS值 } //根據(jù)時間基,計算每一幀的間隔時間 frame_delay = av_q2d(state->video_ctx->time_base); //解碼后的幀要延時的時間 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5); state->video_clock += frame_delay;//得到video_clock,實(shí)際上也是預(yù)測的下一幀視頻的時間 return pts;}

    同步

    上面兩步獲得了Audio_Clock和Video_Clock,這樣我們就有了視頻流中Frame的顯示時間,并且得到了作為基準(zhǔn)時間的音頻播放時長Audio clock ,可以將視頻同步到音頻了。

  • 用當(dāng)前幀的PTS – 上一播放幀的PTS得到一個延遲時間
  • 用當(dāng)前幀的PTS和Audio_Clock進(jìn)行比較,來判斷視頻的播放速度是快了還是慢了
  • 根據(jù)2的結(jié)果,設(shè)置播放下一幀的延遲時間
  • #define AV_SYNC_THRESHOLD 0.01 // 同步最小閾值#define AV_NOSYNC_THRESHOLD 10.0 // 不同步閾值double actual_delay, delay, sync_threshold, ref_clock, diff;// 當(dāng)前Frame時間減去上一幀的時間,獲取兩幀間的延時delay = vp->pts – is->frame_last_pts;if (delay = 1.0) { // 延時小于0或大于1秒(太長)都是錯誤的,將延時時間設(shè)置為上一次的延時時間 delay = is->frame_last_delay;}// 獲取音頻Audio_Clockref_clock = get_audio_clock(is);// 得到當(dāng)前PTS和Audio_Clock的差值diff = vp->pts – ref_clock;sync_threshold = (delay > AV_SYNC_THRESHOLD) ? delay : AV_SYNC_THRESHOLD;// 調(diào)整播放下一幀的延遲時間,以實(shí)現(xiàn)同步if (fabs(diff) frame_timer += delay;// 最終真正要延時的時間actual_delay = is->frame_timer – (av_gettime() / 1000000.0);if (actual_delay < 0.010) { // 延時時間過小就設(shè)置個最小值 actual_delay = 0.010;}// 根據(jù)延時時間刷新視頻schedule_refresh(is, (int) (actual_delay * 1000 + 0.5));

    最后

    將視頻同步到音頻上實(shí)現(xiàn)音視頻同步基本完成,總體就是動態(tài)的過程快了就等待,慢了就加速,在一個你追我趕的狀態(tài)下實(shí)現(xiàn)同步播放。

    后面的博客會持續(xù)更新真正實(shí)現(xiàn)一個音視頻同步的播放器。

    分享一個非常好的音視頻學(xué)習(xí)地址,可點(diǎn)擊免費(fèi)報名訂閱學(xué)習(xí),先關(guān)注不迷路。[給力]

    【免費(fèi)】FFmpeg/WebRTC/RTMP/NDK/Android音視頻流媒體高級開發(fā)-學(xué)習(xí)視頻教程-騰訊課堂

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
    用戶投稿
    上一篇 2022年6月20日 09:10
    下一篇 2022年6月20日 09:11

    相關(guān)推薦

    • 抖音只說了封禁沒說時長(抖音封禁一般多長時間)

      最近是不是發(fā)現(xiàn)抖音監(jiān)管和封號的力度大了很多,我常能看到,有同學(xué)吐槽,為什么又被封了,我也沒有違規(guī)呀?。?那么今天,我就列出4大容易被封的原因,幫你避開90%的坑。學(xué)會了就點(diǎn)贊吧。 …

      2022年11月27日
    • 短視頻策劃內(nèi)容的3個要點(diǎn)(短視頻策劃內(nèi)容怎么做)

      短視頻在制作時,內(nèi)容框架非常重要。如果直奔主題,然后結(jié)束,聚卓告訴你,這樣的短視頻已經(jīng)過時了。現(xiàn)在的短視頻需要框架的,但不是任何框架,它需要一種易于理解和消化的框架。而且,現(xiàn)在大多…

      2022年11月27日
    • TES官宣knight斷開連接!網(wǎng)友:左手就是下一個369

      2022LPL冬季轉(zhuǎn)會期已經(jīng)正式到來,如果說此次轉(zhuǎn)會期熱度最高的一支隊(duì)伍,無疑就是在2022全球總決賽中拿到四強(qiáng)成績的JDG了。因?yàn)閾?jù)目前網(wǎng)上爆料人的消息來看,JDG很有可能會通過…

      2022年11月27日
    • 個人怎么做抖音帶貨(個人做抖音帶貨能賺錢嗎)

      抖音如今是大家很熟悉的短視頻平臺,不過現(xiàn)在的抖音卻不只是短視頻那么簡單,它的功能非常豐富,其中一個就是可以帶貨,相信很多小伙伴都有在抖音上買過東西,抖音如今的變現(xiàn)能力也是不容小覷的…

      2022年11月25日
    • 全民K歌升級新版本7.0之后,有哪些隱藏功能?

      作者:高百烈來源:知乎 這個功能,舊版并沒有,要升級到全新的全民K歌7.0版本才能發(fā)現(xiàn)。 作為朋友圈當(dāng)代K歌之王,我費(fèi)了不少功夫才搶到內(nèi)測版本。有一說一,全民K歌的路子真的很野,新…

      2022年11月25日
    • “濛翔”搭檔展現(xiàn)不一樣的世界杯 中國移動咪咕多檔綜藝上線

      2022國際足聯(lián)卡塔爾世界杯如火如荼進(jìn)行中,王濛、黃健翔冬奧之后再聚首,作為咪咕嘉賓天團(tuán)的成員,不僅陪伴觀眾直擊現(xiàn)場,暢聊世界杯賽場內(nèi)外趣事,更攜手于11月26日、11月30日在咪…

      2022年11月25日
    • 5+3疫情防控從哪天開始算(遼寧疫情防控最新政策)

      最近有關(guān)國內(nèi)各地的疫情大家也都有在持續(xù)關(guān)注,目前國內(nèi)各地疫情隔離時間也根據(jù)二十條防控措施有了新的調(diào)整。那么,5+3疫情防控從哪天開始算?對于密接的5+3隔離時間計算大家還是比較關(guān)心…

      2022年11月25日
    • 藍(lán)碼怎么變綠碼需要幾天(藍(lán)碼怎么變綠碼需要幾天)

      大家都知道健康碼的顏色有紅碼、綠碼、黃碼,近日湖南健康碼上線“藍(lán)碼”,不少小伙伴發(fā)現(xiàn)自己健康碼變藍(lán)了,都想趕緊恢復(fù)綠碼,那么藍(lán)碼怎么變綠碼需要幾天?下面小編為大家?guī)硭{(lán)碼變綠碼需要…

      2022年11月25日
    • 拼多多百億補(bǔ)貼預(yù)售一般多久發(fā)貨(拼多多百億補(bǔ)貼預(yù)售)

      拼多多里面有很多優(yōu)惠活動,其中百億補(bǔ)貼活動非?;鸨?,一些里面的東西價格比別的平臺便宜,質(zhì)量也有保障,還有預(yù)售的活動,那么拼多多百億補(bǔ)貼預(yù)售一般多久發(fā)貨?下面小編為大家?guī)砥炊喽喟賰|…

      2022年11月25日
    • 北京疫情多久能解除封控(北京疫情還要多久結(jié)束)

      最近一段時間北京疫情形勢備受關(guān)注,馬上就要到年底了,不少人想要去北京辦事,。都非常關(guān)注當(dāng)?shù)匾咔橄嚓P(guān)政策,那么 北京疫情多久能解除封控?北京疫情什么時候恢復(fù)正常生活?下面小編為大家?guī)А?/p>

      2022年11月25日

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時間:周一至周五,10:30-18:30,節(jié)假日休息