ビデオ用のスクローラーとObjective-Cの時間表現の理解





こんにちは、ガーディアン!



この記事では、最新のiOSプロジェクトの1つでビデオを操作した経験を共有したいと思います。 詳細には触れません。ハブ、github、その他のインターネットを検索しても解決できないタスクの1つだけを説明します。 タスクは次のとおりでした。ビデオ用のスクローラーを作成することですが、単純ではありませんが、標準のiOS 7ギャラリーのようにすることです。







なぜなら 標準コンポーネントMPMoviePlayerViewControllerを使用してビデオを再生し、ビデオを任意の位置に巻き戻すことをサポートします。主なタスクは、ビデオから定期的に画像を取得してUIViewに配置し、ほぼ現在の位置の下になるようにすることです。ビデオ。 少し先を走りながら、iPadでビデオから画像を生成する際のブレーキ、デバイスの垂直方向と水平方向でのスライダーの長さの違いなど、さらに2つの問題を解決する必要がありました。



そのため、まず最初に、ビデオから写真を取得する方法を理解する必要があります。 AVAssetImageGeneratorはこれを支援します。 このクラスは、ビデオの任意の場所から写真を受信するために特別に作成されます。 テストファイルはホームフォルダーにあり、 test.movと呼ばれると仮定します。



NSString *filepath = [NSString stringWithFormat:@"%@/Documents/test.mov", NSHomeDirectory()]; NSURL *fileURL = [NSURL fileURLWithPath:filepath];
      
      







AVAssetImageGeneratorの使用例:



 // create asset AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:fileURL options:nil]; // create generator AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; // time for preview CMTime time = CMTimeMake(1, 2); // get image ref CGImageRef imageRef = [generator copyCGImageAtTime:time actualTime:nil error:nil]; // create image UIImage *image = [UIImage imageWithCGImage:oneRef];
      
      







以前CMTimeに出くわしていませんでした。時間を等間隔に分割するために、このデータ構造が何であるかを理解することは悪くありません。



CMTimeMakeは、入力として2つの引数valuetimescaleを取ります。 私は公式文書を読みましたが、これらの議論が何であるかを知らない人に簡単な言葉で説明したいと思います。

まず、 タイムスケールは各秒を分割する数です。 この引数を使用して、目的の時点を指定できる精度を指定します。 たとえば、10に等しいタイムスケールを指定すると、1/10秒を取得できます。

同様に、 timescaleを考慮して、時間の望ましい部分を示します。 たとえば、ビデオの長さは60秒、 タイムスケールは10秒で30秒、 は300になります。

CMTimeを使用した時間表現をよりよく理解するために、ビデオの現在の瞬間の秒数はvalue / timescaleに等しいと言います。 前の例から、30秒は300/10です。 秒からCMTimeへ 、またはその逆への時間の変換を理解していれば、この構造に問題はないはずです。



さあ、ビデオの長さを知る必要があります。 とても簡単です。以前に作成したアセットオブジェクトには、必要なプロパティが既にあります。



 CMTime duration = asset.duration;
      
      







さて、ビデオをたくさんの写真にカットするすべてがあります。 ここで問題となるのは、デバイスのポートレートおよびランドスケープの向きにどれだけ必要かということです。 最初に注意する必要があるのは、iPhoneおよびiPadの標準ギャラリーのスクローラーの高さです。 はい、ほぼ同じで、幅だけが異なります。 画像の数がスライダーの幅を1つの画像の幅で割ったものに等しいと推測することは難しくありません。 29x29ピクセルの正方形の画像を作成することにしました。 ここには微妙な点が1つあります。ジェネレーターでは、画像のサイズをピクセル単位で指定する必要があるため、値は58x58になります。



 generator.maximumSize = CGSizeMake(58.0, 58.0);
      
      







単純さと利便性のために、で指定した画像の数は



 #define iPad (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) #define ThumbnailsCountInPortrait (iPad ? 25 : 10) #define ThumbnailsCountInLandscape (iPad ? 38 : 15)
      
      







これで、写真を生成する準備がすべて整いました。 私は2つの異なるアレイを作成しました、なぜなら 縦向きと横向きでは、ビデオの写真は異なります。



 NSMutableArray *portraitThumbnails = [NSMutableArray array]; NSMutableArray *landscapeThumbnails = [NSMutableArray array]; // generate portrait thumbnails for (NSInteger i=0; i < ThumbnailsCountInPortrait; i++) { CMTime time = CMTimeMake(duration.value/ThumbnailsCountInPortrait*i, duration.timescale); CGImageRef oneRef = [generator copyCGImageAtTime:time actualTime:nil error:nil]; [portraitThumbnails addObject:[UIImage imageWithCGImage:oneRef]]; } // generate landscape thumbnails for (NSInteger i=0; i < ThumbnailsCountInLandscape; i++) { CMTime time = CMTimeMake(duration.value/ThumbnailsCountInLandscape*i, duration.timescale); CGImageRef oneRef = [generator copyCGImageAtTime:time actualTime:nil error:nil]; [landscapeThumbnails addObject:[UIImage imageWithCGImage:oneRef]]; }
      
      







ここで、受け取った画像をUIViewの行に配置する方法、さらにはデバイスの向きが異なるさまざまな配列からそれらを取得する方法を伝えるのは適切ではないと思います。 これは実際には複雑なことではなく、完成した例ですべて見ることができます。



最後に、ブレーキの問題を解決する方法についてお話したいと思います。 なぜなら コントローラーの起動時にスライダーが初期化されると、現在のコントローラーへのアニメーションの移行に遅延が生じます。 最も簡単なソリューションはdispatch_asyncです。 この非常に便利なことにより、アプリケーションの速度を落とすことなく、ブロックのコンテンツをバックグラウンドで非同期に実行できます。



使用例:



 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [videoScroller initializeThumbnails]; dispatch_async(dispatch_get_main_queue(), ^{ [videoScroller loadThumbnails]; }); });
      
      







videoScrollerは、バックグラウンドでデータを初期化してからロードするオブジェクトであることは明らかだと思います。



実用的な例はここから入手できます: https : //github.com/iBlacksus/BLVideoScroller



PS

これは私の最初の記事です。行商人にとって興味深いことが判明した場合、私の経験を共有する準備ができています。特に、任意のパレットからテキストの色を選択できるスライダーの作成に関する記事を書く予定です。これは単なる写真です。



All Articles