亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                FFmpeg音視頻同步

                FFmpeg音視頻同步

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

                音視頻同步簡介

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

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

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

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

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

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

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

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

                存放幀順序:I P B B

                解碼時(shí)間戳:1 4 2 3

                展示時(shí)間戳:1 2 3 4

                • 時(shí)間基

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

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

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

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

                Audio_Clock

                Audio_Clock,也就是Audio的播放時(shí)長,從開始到當(dāng)前的時(shí)間。獲取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)星號(hào)獲取,領(lǐng)取資料一定要備注來源:“007”,會(huì)優(yōu)先通過

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

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

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

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

                Video_Clock

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

                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); // 時(shí)間基換算,單位為秒 pts = synchronize_video(state, pFrame, pts); av_packet_unref(packet);}

                舊版的FFmpeg使用av_frame_get_best_effort_timestamp函數(shù)獲取視頻的最合適PTS,新版本的則在解碼時(shí)生成了best_effort_timestamp。但是依然可能會(huì)獲取不到正確的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錯(cuò)誤,使用上一次的PTS值 } //根據(jù)時(shí)間基,計(jì)算每一幀的間隔時(shí)間 frame_delay = av_q2d(state->video_ctx->time_base); //解碼后的幀要延時(shí)的時(shí)間 frame_delay += src_frame->repeat_pict * (frame_delay * 0.5); state->video_clock += frame_delay;//得到video_clock,實(shí)際上也是預(yù)測的下一幀視頻的時(shí)間 return pts;}

                同步

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

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

                最后

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

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

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

                【免費(fèi)】FFmpeg/WebRTC/RTMP/NDK/Android音視頻流媒體高級(jí)開發(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)推薦

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

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

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

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

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

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

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

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

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

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

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

                  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)各地疫情隔離時(shí)間也根據(jù)二十條防控措施有了新的調(diào)整。那么,5+3疫情防控從哪天開始算?對(duì)于密接的5+3隔離時(shí)間計(jì)算大家還是比較關(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)惠活動(dòng),其中百億補(bǔ)貼活動(dòng)非?;鸨?,一些里面的東西價(jià)格比別的平臺(tái)便宜,質(zhì)量也有保障,還有預(yù)售的活動(dòng),那么拼多多百億補(bǔ)貼預(yù)售一般多久發(fā)貨?下面小編為大家?guī)砥炊喽喟賰|…

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

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

                  2022年11月25日

                聯(lián)系我們

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