2012-02-09 78 views
2

我刚刚作出了一个简单的应用程序,它使用QTKit合并两个视频一起QTKit - 合并两个不同宽度和高度的视频?

这里是问题:

刚才我发现,如果我尝试合并两个具有不同宽度&两个视频高度输出是一个视频,其高度和宽度与大视频相同,但包含黑色和宽边框的小视频。

问:

我该如何合并两个视频一起,并用正确的格式(宽/高)得到一个输出视频?

实例更好地了解我需要什么:

我有两个视频:

视频1 = 1920×1280 视频2 = 1280 * 960

我想要的:视频在1920 x 1280(需要放大和裁剪小的一个)

代码:

-(void)voidMethodToCombine { 


NSError *err = nil; 
QTMovie *myCombinedMovie = [[QTMovie alloc] initToWritableData:[NSMutableData data] error:&err]; 
if (err) 
{ 
    NSRunAlertPanel(@"Errore nella creazione del video",[err localizedDescription], nil, @"Chiudi", nil, nil); 
    return; 
    return; 
} 


// Create the File Open Dialog class. 
NSSavePanel *savePanel = [NSSavePanel savePanel]; //Dove salvo il video ? 


if ([savePanel runModal])//Se premo ok 
{ 
    [indicatore setUsesThreadedAnimation:YES]; 
    [indicatore startAnimation:self]; 
    NSURL *saveURL = savePanel.URL; 
    NSString *savePath = [saveURL path]; 
//Prelevo i 2 percorsi e gli inserisco negli array 

NSString *video1 = [URLVideo1 stringValue]; 
NSString *video2 = [URLVideo2 stringValue]; 

NSURL *theURLvideo1 = [NSURL fileURLWithPath:video1]; 

NSURL *theURLvideo2 = [NSURL fileURLWithPath:video2]; 

if((theURLvideo1) && (theURLvideo2)) { 



NSArray *myMovieURLs = [NSArray arrayWithObjects:theURLvideo1,theURLvideo2, nil]; 

for (NSURL *url in myMovieURLs) 
{ 
    QTMovie *theMovie = [QTMovie movieWithURL:url error:&err]; 
    if (err){ 
     NSRunAlertPanel(@"Errore durante il caricamento di uno dei film",[err localizedDescription], nil, @"Chiudi", nil, nil); 
     return; 
    } 
    QTTimeRange timeRange = QTMakeTimeRange(QTZeroTime, [theMovie duration]); 
    QTTime insertionTime = [myCombinedMovie duration]; 
    [myCombinedMovie insertSegmentOfMovie:theMovie timeRange:timeRange atTime:insertionTime]; 
} 

NSDictionary *writeAttributes = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], QTMovieFlatten, nil]; 
//Pannello di path salvataggio 

bool success = [myCombinedMovie writeToFile:savePath withAttributes:writeAttributes error:&err]; 




[indicatore stopAnimation:self]; 
NSBeep(); 
NSString *dove = [[NSString alloc] initWithFormat:@"Video esportato in:\n%@",savePath]; 
NSRunAlertPanel(@"Esportazione avvenuta con successo!", dove, @"Ok", nil, nil); 

if (!success) 
{ 
    NSRunAlertPanel(@"Errore durante il salvataggio del video.",[err localizedDescription], nil, @"Chiudi", nil, nil); 
    return; 
    return; 
} 
} 
//Se non esiste alcun percorso 
else { 

    NSRunAlertPanel(@"Impossibile selezionare i file.", @"Controlla di aver specificato un percorso.", @"Chiudi", nil, nil); 
} 

回答

3

要做到这一点,最简单的方法是使用AVFoundation框架而不是QTKit,因为编辑/操作视频要容易得多(imo),尽管它看起来速度稍慢,代码可能不太紧凑。

我建议你通过阅读AVFoundation编程指南在https://developer.apple.com/library/mac/documentation/AudioVideo/Conceptual/AVFoundationPG/AVFoundationPG.pdf

开始但这里有一个基本的例子,让你开始。在开始之前,确保您已经链接到AVFoundation和CoreMedia框架。

除了任何其他方法或ivars,您可能需要添加AVAssetExportSession *exporterNSTimer *timer以及方法- (void) monitorProgress;

然后,您的实现文件将包含以下方法(假设您使用称为doIt的IBAction触发该方法)。而且不要忘了#import <AVFoundation/ AVFoundation.h>#import <CoreMedia/CoreMedia.h>

- (IBAction)doIt:(id)sender { 
// Initial array of movie URLs 
NSArray *myMovieURLs = [NSArray arrayWithObjects:[NSURL fileURLWithPath:@"/path/to/first.mov"], [NSURL fileURLWithPath:@"/path/to/second.mov"], nil]; 

// Create the composition & A/V tracks 
AVMutableComposition *comp = [AVMutableComposition composition]; 
AVMutableCompositionTrack *compositionVideoTrack = [comp addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
AVMutableCompositionTrack *compositionAudioTrack = [comp addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 

// A reference for insertion start time 
CMTime startTime = kCMTimeZero; 

for (int i=0; i< [myMovieURLs count]; i++){ 
    // Get asset 
    NSURL *movieURL = [myMovieURLs objectAtIndex:i]; 
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:movieURL options:nil]; 

    // Get video and audio tracks (assuming video exists - test for audio as an empty track will crash the program!) and insert in composition tracks 
    AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]; 
    bool success = [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:videoTrack atTime:startTime error:nil]; 

    if ([[asset tracksWithMediaType:AVMediaTypeAudio]count]){ 
     AVAssetTrack *audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 
     success = [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:audioTrack atTime:startTime error:nil]; 
    } 

    // increment the start time to the end of this first video 
    startTime = CMTimeAdd(startTime, [asset duration]); 
} 

//Set the output URL 
NSURL *outputURL = [NSURL fileURLWithPath:@"/path/to/output.mov"]; 

/* Create the exporter. 
Note the preset type is up to you to choose. If you wanted, you could check the asset's size (with [asset naturalSize]) or other values above and use that to base your preset on. 
Use exportPresetsCompatibleWithAsset: to get a list of presets that are compatible with a specific asset. 
*/ 
NSLog(@"Compat presets you could use: %@", [AVAssetExportSession exportPresetsCompatibleWithAsset:comp]); 
exporter = [[AVAssetExportSession alloc] initWithAsset:comp presetName:AVAssetExportPreset640x480]; 

[exporter setOutputURL:outputURL]; 
[exporter setOutputFileType:AVFileTypeQuickTimeMovie]; 
[exporter exportAsynchronouslyWithCompletionHandler:^(void){ 
    switch ([exporter status]) { 
     case AVAssetExportSessionStatusFailed: 
      NSLog(@"Export failed: %@", [[exporter error] localizedDescription]); 
      break; 
     case AVAssetExportSessionStatusCancelled: 
      NSLog(@"Export canceled"); 
      break; 
     default: 
      break; 
    } 
}]; 

// This is just a simple timer that will call a method to log the progress 
timer=[NSTimer scheduledTimerWithTimeInterval:5 
             target:self 
            selector:@selector(monitorProgress) 
            userInfo:nil 
             repeats:YES]; 
} 



-(void)monitorProgress{ 
if ([exporter progress] == 1.0){ 
    [timer invalidate]; 
} 

NSLog(@"Progress: %f",[exporter progress]* 100); 

}

+0

好, 我已经导入了AVFramework并在头宣布它。 然后,我编辑我的代码,并没有错误,直到我试图建立。 我做了一个[***截图***](http://img838.imageshack.us/img838/9009/errorng.png)它。 基本上,它是这样说: ** - [LDAppDelegate doIt方法:]在LDAppDelegate.o LD:符号(多个)未找到架构x86_64的 铛:错误:连接器命令,退出代码1(使用失败 - v看到调用)** 谢谢。 – 2012-02-10 17:37:40

+0

我做了两个截图,让你更好的理解: {[***头文件***](http://img696.imageshack.us/img696/9314/headerui.png) - [*** Implementation file ***](http://img23.imageshack.us/img23/8735/implementation.png)} – 2012-02-10 17:45:53

+0

您会注意到它在第一个屏幕截图中(错误之一)这些问题与kCMTimeZero,CMTimeRangeMake等有关。它们来自CoreMedia框架。您需要添加CoreMedia框架并导入它。这应该解决编译问题。我会编辑我的回答,提到最初我的想法。 – VsSoft 2012-02-10 19:05:33

相关问题