2017-04-10 14 views
1

私はビデオを再生するアプリケーションで作業しており、ビデオ内で前後にスクラブすることができます。スクラビングはスムーズに行わなければならないため、ビデオ圧縮プロパティーAVVideoMaxKeyFrameIntervalKey:@1を使用してビデオをSDAVAssetExportSessionに書き換え、各フレームがキーフレームとなり、スムーズな逆スクラブが可能になります。これは素晴らしい作品で、滑らかな再生を提供します。アプリケーションはさまざまなソースからのビデオを使用し、アンドロイドまたはiOSデバイスに記録され、ウェブからダウンロードしてアプリケーションに追加することもできます。その結果、いくつかはすでにスクラビングに適しています(各フレームキーフレームです)。不必要なビデオ処理を避けるために、ビデオファイルのキーフレーム間隔を検出する方法はありますか?私はAVFoundationの文書の多くを読んできましたが、この情報を入手する明確な方法は見当たりません。これに関する助けをありがとう。AVAssetの現在のキーフレーム間隔を検出する

答えて

1

AVAssetReaderTrackOutputをnil outputSettingsで作成して、イメージをデコードせずにファイルをすばやく解析できる場合は、あなたが遭遇するフレームサンプルバッファには、役に立つ情報を持つ辞書を含む添付ファイル配列があり、フレームが他のフレームに依存するかどうか、または他のフレームがそれに依存するかどうかが含まれます。私は前者をキーフレームを示すものとして解釈しますが、それは私にいくつかの低い数値を与えます(1つのファイルに4%のキーフレーム?)。とにかく、コード:

let asset = AVAsset(url: inputUrl) 
let reader = try! AVAssetReader(asset: asset) 

let videoTrack = asset.tracks(withMediaType: AVMediaTypeVideo)[0] 
let trackReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: nil) 

reader.add(trackReaderOutput) 
reader.startReading() 

var numFrames = 0 
var keyFrames = 0 

while true { 
    if let sampleBuffer = trackReaderOutput.copyNextSampleBuffer() { 
     // NB: not every sample buffer corresponds to a frame! 
     if CMSampleBufferGetNumSamples(sampleBuffer) > 0 { 
      numFrames += 1 
      if let attachmentArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, false) as? NSArray { 
       let attachment = attachmentArray[0] as! NSDictionary 
       // print("attach on frame \(frame): \(attachment)") 
       if let depends = attachment[kCMSampleAttachmentKey_DependsOnOthers] as? NSNumber { 
        if !depends.boolValue { 
         keyFrames += 1 
        } 
       } 
      } 
     } 
    } else { 
     break 
    } 
} 

print("\(keyFrames) on \(numFrames)") 

N.B.これは、ローカルファイルアセットでのみ機能します。

p.s.あなたはスクラブや遊びの方法を言っていません。 AVPlayerViewControllerAVPlayer

+0

回答ありがとうございます。私は今日これを実装しました(目的はCです)。私はAVPlayerとAVPlayerLayerでカスタムUIViewを使用しています。これはかなり正確で、すべてのキーフレームを使用するようにエンコードしたビデオの約96%のキーフレームを返します。他の圧縮設定の動画の方がずっと少なくなりました。スクラバーは、スクロール速度をスクラブループに変換して一度に1つのフレームにステップするホイール(scrollView)です。 Qへの回答として私の方法を掲載するかもしれません。私はこれのObjective cバージョンも投稿します。 – johnrechd

+0

クール!私はそれを見ることを楽しみにしています。それは欠けている4%について奇妙です。私はその説明が何であるか疑問に思います。 –

1

ここでは、同じ回答のObjective Cバージョンです。これを実装して使用すると、すべてのキーフレームが必要なビデオは、このコードから約96%のキーフレームを返しています。なぜ私はそれがより正確であることを望んでいるにもかかわらず、私は決定要因としてその数を使用しています。私はこの決定をするために20分のビデオ全体を読む必要はないので、最初の600フレームまたはビデオの終わり(最初のどちらか早い方)を見ているだけです。

+ (BOOL)videoNeedsProcessingForSlomo:(NSURL*)fileUrl { 
    BOOL needsProcessing = YES; 
    AVAsset* anAsset = [AVAsset assetWithURL:fileUrl]; 
    NSError *error; 
    AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:anAsset error:&error]; 
    if (error) { 
     DLog(@"Error:%@", error.localizedDescription); 
     return YES; 
    } 

    AVAssetTrack *videoTrack = [[anAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 

    AVAssetReaderTrackOutput *trackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:nil]; 
    [assetReader addOutput:trackOutput]; 

    [assetReader startReading]; 

    float numFrames = 0; 
    float keyFrames = 0; 

    while (numFrames < 600) { // If the video is long - only parse through 20 seconds worth. 
     CMSampleBufferRef sampleBuffer = [trackOutput copyNextSampleBuffer]; 
     if (sampleBuffer) { 
      // NB: not every sample buffer corresponds to a frame! 
      if (CMSampleBufferGetNumSamples(sampleBuffer) > 0) { 
       numFrames += 1; 

       NSArray *attachmentArray = ((NSArray*)CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, false)); 
       if (attachmentArray) { 
        NSDictionary *attachment = attachmentArray[0]; 
        NSNumber *depends = attachment[(__bridge NSNumber*)kCMSampleAttachmentKey_DependsOnOthers]; 
        if (depends) { 
         if (depends.boolValue) { 
          keyFrames += 1; 
         } 
        } 
       } 
      } 
     } 
     else { 
      break; 
     } 
    } 

    needsProcessing = keyFrames/numFrames < 0.95f; // If more than 95% of the frames are keyframes - don't decompress. 

    return needsProcessing; 
} 
+0

申し訳ありません - 私はあなたが目的のCを使用していたのか分からなかった、質問はタグ付けされていません –

+0

私のための言語にはあまり関係はありませんでした。あなたのお手伝いをありがとう。私は似たようなものを持っていて、たくさんのドキュメンテーションを通して読んでいましたが、kCMSampleAttachmentKey_DependsOnOthersを使ってこれを判断することができるかどうかは分かりませんでした。 – johnrechd

関連する問題