19

私のアプリケーションでは、ビデオをキャプチャし、そのビデオに透かしを入れる必要があります。透かしはテキスト (時間とメモ) である必要があります。「QTKit」フレームワークを使ったコードを見ました。ただし、このフレームワークは iPhone では利用できないと読みました。

前もって感謝します。

4

6 に答える 6

48

透かしの追加は非常に簡単です。CALayer と AVVideoCompositionCoreAnimationTool を使用するだけです。コードをコピーして、同じ順序で組み立てることができます。理解を深めるために、間にいくつかのコメントを挿入しようとしました。

すでにビデオを録画していると仮定して、最初に AVURLAsset を作成します。

AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL:outputFileURL options:nil];
AVMutableComposition* mixComposition = [AVMutableComposition composition];

AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo  preferredTrackID:kCMPersistentTrackID_Invalid];
AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) 
                               ofTrack:clipVideoTrack
                                atTime:kCMTimeZero error:nil];

[compositionVideoTrack setPreferredTransform:[[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] preferredTransform]]; 

このコードだけでビデオをエクスポートできますが、最初に透かしのあるレイヤーを追加したいと思います。一部のコードは冗長に見えるかもしれませんが、すべてが機能するために必要であることに注意してください。

まず、透かし画像を含むレイヤーを作成します。

UIImage *myImage = [UIImage imageNamed:@"icon.png"];
CALayer *aLayer = [CALayer layer];
aLayer.contents = (id)myImage.CGImage;
aLayer.frame = CGRectMake(5, 25, 57, 57); //Needed for proper display. We are using the app icon (57x57). If you use 0,0 you will not see it
aLayer.opacity = 0.65; //Feel free to alter the alpha here

画像ではなくテキストが必要な場合:

CATextLayer *titleLayer = [CATextLayer layer];
titleLayer.string = @"Text goes here";
titleLayer.font = @"Helvetica";
titleLayer.fontSize = videoSize.height / 6;
//?? titleLayer.shadowOpacity = 0.5;
titleLayer.alignmentMode = kCAAlignmentCenter;
titleLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height / 6); //You may need to adjust this for proper display

次のコードは、レイヤーを適切な順序で並べ替えます。

CGSize videoSize = [videoAsset naturalSize]; 
CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];   
parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
[parentLayer addSublayer:videoLayer];
[parentLayer addSublayer:aLayer];
[parentLayer addSublayer:titleLayer]; //ONLY IF WE ADDED TEXT

ここで、コンポジションを作成し、レイヤーを挿入するための指示を追加します。

AVMutableVideoComposition* videoComp = [[AVMutableVideoComposition videoComposition] retain];
videoComp.renderSize = videoSize;
videoComp.frameDuration = CMTimeMake(1, 30);
videoComp.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

/// instruction
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, [mixComposition duration]);
AVAssetTrack *videoTrack = [[mixComposition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableVideoCompositionLayerInstruction* layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
videoComp.instructions = [NSArray arrayWithObject: instruction];

これで、エクスポートする準備が整いました:

_assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetMediumQuality];//AVAssetExportPresetPassthrough   
_assetExport.videoComposition = videoComp;

NSString* videoName = @"mynewwatermarkedvideo.mov";

NSString *exportPath = [NSTemporaryDirectory() stringByAppendingPathComponent:videoName];
NSURL    *exportUrl = [NSURL fileURLWithPath:exportPath];

if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath]) 
{
    [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
}

_assetExport.outputFileType = AVFileTypeQuickTimeMovie; 
_assetExport.outputURL = exportUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;

[strRecordedFilename setString: exportPath];

[_assetExport exportAsynchronouslyWithCompletionHandler:
 ^(void ) {
     [_assetExport release];
     //YOUR FINALIZATION CODE HERE
 }       
 ];   

[audioAsset release];
[videoAsset release];
于 2012-01-10T02:43:33.817 に答える
15

を使用しAVFoundationます。AVCaptureVideoDataOutputでフレームを取得し、キャプチャしたフレームに透かし画像を重ね、最後にキャプチャして処理したフレームをファイル user に書き込むことをお勧めしますAVAssetWriter

スタックオーバーフローを検索してください。私が言及したこれらのそれぞれを行う方法を詳述した素晴らしい例がたくさんあります。希望する効果を正確に示すコード例は見たことがありませんが、かなり簡単に組み合わせることができるはずです。

編集:

これらのリンクを見てください:

iPhone: AVCaptureSession キャプチャ出力のクラッシュ (AVCaptureVideoDataOutput) - この投稿は、関連するコードが含まれているという性質上、役立つ場合があります。

AVCaptureDataOutputCMSampleBufferRefは画像をsとして返します。CGImageRef次のコードを使用して、それらを s に変換します。

    - (CGImageRef) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer // Create a CGImageRef from sample buffer data
{

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer,0);        // Lock the image buffer 

    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);   // Get information of the image 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef newImage = CGBitmapContextCreateImage(newContext); 
    CGContextRelease(newContext); 

    CGColorSpaceRelease(colorSpace); 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 
    /* CVBufferRelease(imageBuffer); */  // do not call this!

    return newImage;
}

そこから UIImage に変換します。

  UIImage *img = [UIImage imageWithCGImage:yourCGImage];  

次に使用します

[img drawInRect:CGRectMake(x,y,height,width)]; 

フレームをコンテキストに描画するには、その上に透かしの PNG を描画し、AVAssetWriter. 大量の UIImage でメモリがいっぱいにならないように、リアルタイムで追加することをお勧めします。

UIImage 配列をムービーとしてエクスポートするにはどうすればよいですか? - この投稿では、処理した UIImage を特定の期間ビデオに追加する方法を示します。

これにより、動画に透かしを入れる準備が整います。20 ~ 30 fps で入ってくる画像のリークは、アプリをクラッシュさせるのに最適な方法であるため、適切なメモリ管理を実践することを忘れないでください。

于 2011-08-26T14:25:13.287 に答える
2

コードをダウンロードして使用するだけです。Apple 開発者ドキュメント ページにあります。

http://developer.apple.com/library/ios/#samplecode/AVSimpleEditoriOS/Listings/AVSimpleEditor_AVSERotateCommand_m.html

于 2013-03-06T05:04:43.457 に答える