<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          FFmpeg 音視頻倍速控制

          共 2343字,需瀏覽 5分鐘

           ·

          2022-02-24 20:34

          網(wǎng)上關(guān)于FFmpeg音視頻倍速控制的資料不多,大部分都是講通過(guò)FFmpeg命令去做音視頻文件的倍速處理,通過(guò)FFmpeg api去 處理倍速的資料少之又少。

          本文除了會(huì)講到通過(guò)命令行處理倍速,還會(huì)講到通過(guò)FFmpeg api的方式去處理音頻倍速和視頻倍速,進(jìn)而合并成支持倍速的音視頻發(fā)布成rtmp或者存成flv文件。

          介紹FFmpeg的filter工具

          音視頻的倍速處理少不了filter這個(gè)工具,filter可以翻譯成過(guò)濾器和濾波器。

          按照處理數(shù)據(jù)的類型還可分為音頻filter、視頻filter、字幕filter,F(xiàn)Fmpeg可以通過(guò)filter將音視頻實(shí)現(xiàn)出非常多不同的filter效果,視頻可以實(shí)現(xiàn)縮放、合并、裁剪、旋轉(zhuǎn)、水印添加、倍速等效果,音頻可以實(shí)現(xiàn)回聲、延遲、去噪、混音、音量調(diào)節(jié)、變速等效果。

          我們可以通過(guò)filter不同方式的組合去定制出我們想要的音視頻特效

          介紹FFmpeg命令行倍速

          1、視頻的倍速主要是通過(guò)控制filter中的setpts來(lái)實(shí)現(xiàn),setpts是視頻濾波器通過(guò)改變每一個(gè)pts時(shí)間戳來(lái)實(shí)現(xiàn)倍速的效果,如下只要把PTS縮小一半就可以實(shí)現(xiàn)2倍速,相反的是PTS增加一倍就達(dá)到2倍慢放的效果。

          ffmpeg?-i?in.mp4?-filter:v?"setpts=0.5*PTS"?out.mp4
          ffmpeg?-i?in.mp4?-filter:v?"setpts=2.0*PTS"?out.mp4

          2、音頻的倍速則是通過(guò)控制filter的atempo來(lái)實(shí)現(xiàn),atempo的配置區(qū)間在0.5和2.0之間,如果需要更高倍速,則需要多個(gè)atempo串一起,下面是2、4倍速的實(shí)現(xiàn)命令。

          ffmpeg?-i?in.mp4?-filter:"atempo=2.0"?-vn?out.mp4
          ffmpeg?-i?in.mp4?-filter:"atempo=2.0,atempo=2.0"?-vn?out.mp4

          3、同時(shí)對(duì)音視頻進(jìn)行2倍速。

          ffmpeg?-i?in.mp4?-filter_complex?"[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]"?-map?"[v]"?-map?"[a]"?out.mp4

          視頻倍速

          視頻倍速可以通過(guò)filter的setpts來(lái)更改視頻的倍速,但是filter只對(duì)未編碼的原始視頻數(shù)據(jù)進(jìn)行倍速處理。

          我這邊對(duì)于視頻的處理是將H264進(jìn)行格式封裝,如果使用filter的話,我還需要先對(duì)H264解碼,再做倍速轉(zhuǎn)換,再重新編碼成H264,這樣將會(huì)消耗相當(dāng)多的資源。

          我這邊對(duì)視頻倍速就沒必要用filter進(jìn)行處理。其實(shí)視頻倍速只需要改變封裝格式時(shí)設(shè)置的時(shí)間戳就可以,所以我這邊只要改變video_tempo這個(gè)參數(shù)的值即可,1000是正常倍速、2000是2倍速,依次疊加。

          if?(tempo?!=?video_tempo?&&?(tempo?>=?1000?&&?tempo?<=?16000))?{
          ??video_tempo?=?tempo;
          ??Logger::Info("video_tempo?=?%d",?video_tempo);
          }
          ?AVRational?time_base?=?{?1,?video_tempo};
          ?pkt.pts?=?av_rescale_q((ptsInc++)?*?2,?time_base,?ost->st->time_base);
          ?pkt.dts?=?av_rescale_q_rnd(pkt.dts,?ost->st->time_base,?ost->st->time_base,?(AVRounding)(AV_ROUND_NEAR_INF?|?AV_ROUND_PASS_MINMAX));
          ?pkt.duration?=?av_rescale_q(pkt.duration,?ost->st->time_base,?ost->st->time_base);

          音頻倍速

          音頻倍速就需要用到filter進(jìn)行處理了,我這邊對(duì)音頻的處理是,先解碼音頻,然后用filter進(jìn)行倍速處理,對(duì)處理后的音頻數(shù)據(jù)進(jìn)行重采樣再編碼成AAC的音頻格式。

          如果只是對(duì)音頻做處理,不做音視頻封裝,可以直接把filter處理后的數(shù)據(jù)存成PCM,即可驗(yàn)證音頻的倍速。

          1. 初始化filter的abuffer,aformat,abuffersink濾波器,abuffer用于接收輸入frame,形成待處理的數(shù)據(jù)緩存,abuffersink用于傳出輸出Frame,aformat過(guò)濾器約束最終的輸出格式(采樣率,聲道數(shù),存儲(chǔ)位數(shù)等),而中間的其他過(guò)濾器可以串聯(lián)多個(gè)filter,如volume(音量調(diào)節(jié)),atempo(變速)等。
          int?init_atempo_filter(AVFilterGraph?**pGraph,?AVFilterContext?**src,?AVFilterContext?**out,?char?*value)
          {
          ?//初始化AVFilterGraph
          ?AVFilterGraph?*graph?=?avfilter_graph_alloc();
          ?//獲取abuffer用于接收輸入端
          ?const?AVFilter?*abuffer?=?avfilter_get_by_name("abuffer");
          ?AVFilterContext?*abuffer_ctx?=?avfilter_graph_alloc_filter(graph,?abuffer,?"src");
          ?//設(shè)置參數(shù),這里需要匹配原始音頻采樣率8000、數(shù)據(jù)格式(位數(shù):16)、單聲道
          ?if?(avfilter_init_str(abuffer_ctx,?"sample_rate=8000:sample_fmt=s16:channel_layout=mono")?0)?{
          ??Logger::Error("error?init?abuffer?filter");
          ??return?-1;
          ?}
          ?//初始化atempo?filter
          ?const?AVFilter?*atempo?=?avfilter_get_by_name("atempo");
          ?AVFilterContext?*atempo_ctx?=?avfilter_graph_alloc_filter(graph,?atempo,?"atempo");
          ?//這里采用av_dict_set設(shè)置參數(shù)
          ?AVDictionary?*args?=?NULL;
          ?av_dict_set(&args,?"tempo",?value,?0);//這里傳入外部參數(shù),可以動(dòng)態(tài)修改
          ?if?(avfilter_init_dict(atempo_ctx,?&args)?0)?{
          ??Logger::Error("error?init?atempo?filter");
          ??return?-1;
          ?}

          ?const?AVFilter?*aformat?=?avfilter_get_by_name("aformat");
          ?AVFilterContext?*aformat_ctx?=?avfilter_graph_alloc_filter(graph,?aformat,?"aformat");
          ?if?(avfilter_init_str(aformat_ctx,?"sample_rates=8000:sample_fmts=s16:channel_layouts=mono")?0)?{
          ??Logger::Error("error?init?aformat?filter");
          ??return?-1;
          ?}
          ?//初始化sink用于輸出
          ?const?AVFilter?*sink?=?avfilter_get_by_name("abuffersink");
          ?AVFilterContext?*sink_ctx?=?avfilter_graph_alloc_filter(graph,?sink,?"sink");
          ?if?(avfilter_init_str(sink_ctx,?NULL)?0)?{//無(wú)需參數(shù)
          ??Logger::Error("error?init?sink?filter");
          ??return?-1;
          ?}
          ?//鏈接各個(gè)filter上下文
          ?if?(avfilter_link(abuffer_ctx,?0,?atempo_ctx,?0)?!=?0)?{
          ??Logger::Error("error?link?to?atempo?filter");
          ??return?-1;
          ?}
          ?if?(avfilter_link(atempo_ctx,?0,?aformat_ctx,?0)?!=?0)?{
          ??Logger::Error("error?link?to?aformat?filter");
          ??return?-1;
          ?}
          ?if?(avfilter_link(aformat_ctx,?0,?sink_ctx,?0)?!=?0)?{
          ??Logger::Error("error?link?to?sink?filter");
          ??return?-1;
          ?}
          ?if?(avfilter_graph_config(graph,?NULL)?0)?{
          ??Logger::Error("error?config?filter?graph");
          ??return?-1;
          ?}
          ?*pGraph?=?graph;
          ?*src?=?abuffer_ctx;
          ?*out?=?sink_ctx;
          ?Logger::Info("init?filter?success...");
          ?return?0;
          }
          1. 注冊(cè)所有過(guò)濾器
          ????avfilter_register_all();
          ?if?(init_atempo_filter(&s_graph,?&in_ctx,?&out_ctx,?"1.0")?!=?0)?{
          ??Logger::Error("Codec?not?init?audio?filter");
          ??return?-1;
          ?}
          1. 使用過(guò)濾器 將解碼后的AVFrame通過(guò)av_buffersrc_add_frame(in_ctx, pFrameAudio)加入到輸入過(guò)濾器上下文in_ctx中,通過(guò)av_buffersink_get_frame(out_ctx, pFrameAudio)獲取處理完成的pFrameAudio。pFrameAudio就可以直接存成PCM或者再編碼封裝音視頻格式。
          ????//將pFrameAudio放入輸入filter上下文
          ?if?(av_buffersrc_add_frame(in_ctx,?pFrameAudio)?0)?{
          ??Logger::Error("error?add?frame");
          ?}
          ?//從輸出filter上下文中獲取pFrameAudio
          ?while?(av_buffersink_get_frame(out_ctx,?pFrameAudio)?>=?0)?{
          ??break;
          ?}

          動(dòng)態(tài)修改倍速說(shuō)明

          本文由于封裝音視頻倍速的時(shí)候,視頻倍速處理是沒有通過(guò)filter去做的,只是改變視頻幀封裝的時(shí)間戳達(dá)到倍速效果.如果最開始是以正常速度的倍速推流,過(guò)程中再去修改倍速參數(shù),就會(huì)導(dǎo)致要寫進(jìn)的視頻時(shí)間戳大于之前的時(shí)間戳,進(jìn)而出錯(cuò)。

          所以本文講的ffmpeg的API控制音視頻倍速是沒辦法通過(guò)動(dòng)態(tài)調(diào)整倍速的。必須一開始就設(shè)置好倍速,后續(xù)就不能再改動(dòng)。如果單獨(dú)對(duì)音頻進(jìn)行動(dòng)態(tài)修改倍速,則是沒問(wèn)題的。

          作者:RzzZ

          來(lái)源:https://blog.csdn.net/qq_22633333/article/details/104967304

          一個(gè)音視頻領(lǐng)域?qū)I(yè)問(wèn)答的小圈子!

          推薦閱讀:

          音視頻開發(fā)工作經(jīng)驗(yàn)分享 || 視頻版

          OpenGL ES 學(xué)習(xí)資源分享

          開通專輯 | 細(xì)數(shù)那些年寫過(guò)的技術(shù)文章專輯

          Android NDK 免費(fèi)視頻在線學(xué)習(xí)?。?!

          你想要的音視頻開發(fā)資料庫(kù)來(lái)了

          推薦幾個(gè)堪稱教科書級(jí)別的 Android 音視頻入門項(xiàng)目

          覺得不錯(cuò),點(diǎn)個(gè)在看唄~

          瀏覽 54
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品秘 一区二三区在线男奴 | 一级黄色片免费看在干嘛呢 | 国产伦子伦一级A片免费看小说 | 亚洲三级黄色 | 青草青青精品视频在线观看 |