ビデオの結合の問題を解決するために必要なプロジェクトの1つでは、特に、ユーザーはビデオを一時停止してから記録を続行できました(反復回数は不明でした)。 したがって、利用可能な手段でこの問題を解決する方法を見つける必要がありました。 もちろん、一度にすべてを1つのファイルに書き込むか、別のファイルに書き込み、セッション後にそれらを接着するかの2つのオプションがありました。 私は2番目にとどまることにしました、そして、それから来たものは、カットの下で読みました。
ビデオを記録するために、私たちのお気に入りのサイトに親切に配置されたAVCamアプリケーションに基づいてAVCamCaptureManagerを使用しました 。 さて、停止ボタンを押した後、楽しみが始まりました。
ステージ1.準備。
この段階で、次を実行します。
- オブジェクトAVMutableComposition 。 パスがあります。 AVMutableComposition
AVMutableComposition *mixComposition = [[AVMutableComposition alloc] init];
- トラックの命令の配列とそれらのAVMutableVideoCompositionInstructionオブジェクト。 AVMutableVideoCompositionInstruction
NSMutableArray *arrayInstruction = [[NSMutableArray alloc] init]; AVMutableVideoCompositionInstruction *MainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
- 一般的なオーディオトラック。 isSound変数は、ここで必要かどうかを示します(タスクに応じて、ユーザーは音声付きまたは音声なしでビデオを録画できます)。
一般的なオーディオトラックAVMutableCompositionTrack *audioTrack; if(self.isSoundOn==YES) audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
- 期間を保存するための変数(および接着の境界を決定するためにも必要です)。
CMTime duration = kCMTimeZero;
ステージ2.ファイルを検索し、アセットを作成し、指示を生成し、必要に応じてビデオトラックを変換します。
- すべてのファイルを調べて、それぞれのアセットを作成します。 これはすべてループで実行でき、実行する必要があります。変数i-hereはファイルインデックスです。
資産作成iの値を増やしながら、すべてのビデオをテンポディレクトリに記録しました。 したがって、これらのファイルからアセットが作成されます。AVAsset *currentAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@%@%d%@", NSTemporaryDirectory(), @"Movie",i,@".mov"]]];
- ループでは、 AVMutableCompositionTrackが作成され、それぞれに作成されたアセットからの時間間隔CMTimeRangeが挿入されます。 トラック作成再生中に黒いバーを避けたい場合や、さらに悪いことに、再生中に1つのビデオを別のビデオと重複させたくない場合は、セグメントを正確に挿入する場所に特に注意する必要があります。 そして、なぜ私がこれに焦点を合わせているのかを聞かないでください。
//VIDEO TRACK AVMutableCompositionTrack *currentTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; [currentTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, currentAsset.duration) ofTrack:[[currentAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:duration error:nil];
- AVMutableVideoCompositionLayerInstructionは 、トラックの特定のレイヤーの指示を作成するために使用されます。 可能な変換が記録されるのは彼の中でです。 AVMutableVideoCompositionLayerInstruction出力でのビデオ(ポートレートまたはランドスケープスケープ)の位置を正しく定義することで、どのモードの最初のトラックに応じて水平または垂直ビデオが中央に配置される豪華な画像を取得できます。
AVMutableVideoCompositionLayerInstruction *currentAssetLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:currentTrack];
- タイプAVMediaTypeVideoの既存のアセットに基づいてトラックを作成するには、AVAssetTrackオブジェクトが必要です。
AVAssetTrackAVAssetTrack *currentAssetTrack = [[currentAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
- 継続時間の値を増やします。
持続時間UPもちろん、CMTimeには別の投稿も必要です。duration=CMTimeAdd(duration, currentAsset.duration);
ステージ3. MainInstructionパラメーターの設定とAVMutableVideoCompositionの形成
- timeRangeビデオトラックの合計時間。
MainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, duration);
- layerInstructionsここでは、第2段階で形成された命令の配列が必要です。
MainInstruction.layerInstructions = arrayInstruction;
- MainCompositionInst必要なパラメーターを使用してMainCompositionInstのインスタンスを作成します
AVMutableVideoComposition *MainCompositionInst = [AVMutableVideoComposition videoComposition]; MainCompositionInst.instructions = [NSArray arrayWithObject:MainInstruction]; MainCompositionInst.frameDuration = CMTimeMake(1, 30); MainCompositionInst.renderSize = CGSizeMake(320.0, 480.0);
- どこに保存しますか?
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"mergeVideo-%d.mov",arc4random() % 1000]]; NSURL *url = [NSURL fileURLWithPath:myPathDocs];
ステージ4. AVAssetExportSessionを介して受信したビデオを保存する
最高プリセットと中プリセットの違いは非常に重要です。 したがって、ソーシャルネットワークで動画を配信する予定がある場合は、中を使用することを強くお勧めします。
- 品質を設定し、セッションを作成します
NSString *quality = AVAssetExportPresetHighestQuality; if(self.isHighQuality==NO) quality = AVAssetExportPresetMediumQuality; AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:quality];
- セーブ!
exporter.outputURL=url; exporter.outputFileType = AVFileTypeQuickTimeMovie; exporter.videoComposition = MainCompositionInst; exporter.shouldOptimizeForNetworkUse = YES; [exporter exportAsynchronouslyWithCompletionHandler:^ { // . }];
可能なエクスポートステータス:
ここには何がありますか?
switch (exporter.status) { case AVAssetExportSessionStatusCompleted: NSLog(@"Completed exporting!"); break; case AVAssetExportSessionStatusFailed: NSLog(@"Failed:%@", exporter.error.description); break; case AVAssetExportSessionStatusCancelled: NSLog(@"Canceled:%@", exporter.error); break; case AVAssetExportSessionStatusExporting: NSLog(@"Exporting!"); break; case AVAssetExportSessionStatusWaiting: NSLog(@"Waiting"); break; default: break; }
おわりに
記事では、ビデオの結合に焦点を当てようとしましたが、この投稿は、将来このようなタスクに直面するiOS開発に関与する多くのHabrovskの人々に役立つと思います。 将来、私はCMTimeについて、そしてなぜそれが単なる「時間」ではないのかについてもっと話すつもりです。 ところで、トピックに関する多くの有用な情報がサイトにあります 。 メソッド自体はリポジトリで見つけることができます。