2016-07-23 64 views
0

我最初使用AVFoundation庫來修剪視頻,但它有一個侷限性,即它無法爲遠程URL執行操作,並且僅適用於本地URL。iOS ffmpeg如何運行一個命令來修剪遠程URL視頻?

因此,經過進一步的研究,我發現ffmpeg庫可以包含在iOS的Xcode項目中。 我已經測試了下面的命令來修整上的命令行遠程視頻:

ffmpeg -y -ss 00:00:01.000 -i "http://i.imgur.com/gQghRNd.mp4" -t 00:00:02.000 -async 1 cut.mp4 

這將修剪.mp4從1秒到3秒標記。這可以通過我的Mac上的命令行完美工作。

我已經成功編譯並將ffmpeg庫包含到xcode項目中,但不知道如何繼續下一步。

現在我想弄清楚如何在iOS應用程序中使用ffmpeg庫來運行此命令。我怎樣才能做到這一點?

如果你能指點我一些有用的方向,我會非常感激!如果我可以使用你的解決方案來解決它,我會獎勵賞金(2天內,當它給我的選擇)。

回答

0

我對此有一些想法。然而,我在iOS上的exp已經非常有限,不確定我的想法是否是最好的方式:

據我所知,通常不可能在iOS上運行cmd工具。也許你必須編寫一些鏈接到ffmpeg庫的代碼。

這裏需要做的所有工作:

  1. 打開輸入文件和init一些ffmpeg的背景。
  2. 獲取視頻流並尋找您想要的時間戳。這可能很複雜。請參閱ffmpeg tutorial獲得一些幫助,或查看this以精確查找並處理麻煩的關鍵幀。
  3. 解碼一些幀。直到框架匹配結束時間戳。
  4. 與此同時,將幀編碼爲一個新的文件作爲輸出。

ffmpeg源碼中的示例非常適合瞭解如何執行此操作。

一些也許有用代碼:

av_register_all(); 
avformat_network_init(); 

AVFormatContext* fmt_ctx; 
avformat_open_input(&fmt_ctx, "http://i.imgur.com/gQghRNd.mp4", NULL, NULL); 

avformat_find_stream_info(fmt_ctx, NULL); 

AVCodec* dec; 
int video_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &dec, 0); 
AVCodecContext* dec_ctx = avcodec_alloc_context3(NULL); 
avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[video_stream_index]->codecpar) 
// If there is audio you need, it should be decoded/encoded too. 

avcodec_open2(dec_ctx, dec, NULL); 
// decode initiation done 

av_seek_frame(fmt_ctx, video_stream_index, frame_target, AVSEEK_FLAG_FRAME); 
// or av_seek_frame(fmt_ctx, video_stream_index, timestamp_target, AVSEEK_FLAG_ANY) 
// and for most time, maybe you need AVSEEK_FLAG_BACKWARD, and skipping some following frames too. 

AVPacket packet; 
AVFrame* frame = av_frame_alloc(); 

int got_frame, frame_decoded; 
while (av_read_frame(fmt_ctx, &packet) >= 0 && frame_decoded < second_needed * fps) { 
    if (packet.stream_index == video_stream_index) { 
     got_frame = 0; 
     ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &packet); 
     // This is old ffmpeg decode/encode API, will be deprecated later, but still working now. 
     if (got_frame) { 
      // encode frame here 
     } 
    } 
}