2015-02-24 15 views
7

Tác vụ: Kết hợp ảnh quảng cáo vào video của trình phát.Tính năng hợp nhất video trong nền iOS

Các trường hợp:

  • Tạo một tờ [thêm hình ảnh biểu tượng cảm xúc/text..etc]
  • Tạo video nút

Trường hợp1

  • Nhấn trở lại [người dùng sẽ chuyển tới danh sách ứng dụng của tờ rơi s màn hình], trong thời gian này chúng tôi đang hợp nhất flyerSnapShoot trong flyerVideo.and nó hoạt động hoàn hảo.
  • Đi tới Thư viện điện thoại, chúng tôi đang xem video cập nhật trong đó.

Trường hợp2

  • Nhấn nút iPhone đình, tôi đang làm điều tương tự như trên nhưng phải đối mặt với những điều sau lỗi.

FAIL = Lỗi miền = AVFoundationErrorDomain Mã = -11.800 "Các hoạt động không thể hoàn tất" UserInfo = 0x17266d40 {NSLocalizedDescription = Các hoạt động không thể hoàn tất, NSUnderlyingError = 0x172b3920 "Các hoạt động không thể . hoàn thành (. OSStatus lỗi -16.980)", NSLocalizedFailureReason = Có lỗi lạ (-16.980)}

:

- (void)modifyVideo:(NSURL *)src destination:(NSURL *)dest crop:(CGRect)crop 
       scale:(CGFloat)scale overlay:(UIImage *)image 
     completion:(void (^)(NSInteger, NSError *))callback { 

    // Get a pointer to the asset 
    AVURLAsset* firstAsset = [AVURLAsset URLAssetWithURL:src options:nil]; 

    // Make an instance of avmutablecomposition so that we can edit this asset: 
    AVMutableComposition* mixComposition = [AVMutableComposition composition]; 

    // Add tracks to this composition 
    AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 

    // Audio track 
    AVMutableCompositionTrack *audioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 

    // Image video is always 30 seconds. So we use that unless the background video is smaller. 
    CMTime inTime = CMTimeMake(MAX_VIDEO_LENGTH * VIDEOFRAME, VIDEOFRAME); 
    if (CMTimeCompare(firstAsset.duration, inTime) < 0) { 
     inTime = firstAsset.duration; 
    } 

    // Add to the video track. 
    NSArray *videos = [firstAsset tracksWithMediaType:AVMediaTypeVideo]; 
    CGAffineTransform transform; 
    if (videos.count > 0) { 
     AVAssetTrack *track = [videos objectAtIndex:0]; 
     [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, inTime) ofTrack:track atTime:kCMTimeZero error:nil]; 
     transform = track.preferredTransform; 
     videoTrack.preferredTransform = transform; 
    } 

    // Add the audio track. 
    NSArray *audios = [firstAsset tracksWithMediaType:AVMediaTypeAudio]; 
    if (audios.count > 0) { 
     [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, inTime) ofTrack:[audios objectAtIndex:0] atTime:kCMTimeZero error:nil]; 
    } 

    NSLog(@"Natural size: %.2f x %.2f", videoTrack.naturalSize.width, videoTrack.naturalSize.height); 

    // Set the mix composition size. 
    mixComposition.naturalSize = crop.size; 

    // Set up the composition parameters. 
    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 
    videoComposition.frameDuration = CMTimeMake(1, VIDEOFRAME); 
    videoComposition.renderSize = crop.size; 
    videoComposition.renderScale = 1.0; 

    // Pass through parameters for animation. 
    AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    passThroughInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, inTime); 

    // Layer instructions 
    AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack]; 

    // Set the transform to maintain orientation 
    if (scale != 1.0) { 
     CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scale, scale); 
     CGAffineTransform translateTransform = CGAffineTransformTranslate(CGAffineTransformIdentity, 
                      -crop.origin.x, 
                      -crop.origin.y); 
     transform = CGAffineTransformConcat(transform, scaleTransform); 
     transform = CGAffineTransformConcat(transform, translateTransform); 
    } 

    [passThroughLayer setTransform:transform atTime:kCMTimeZero]; 

    passThroughInstruction.layerInstructions = @[ passThroughLayer ]; 
    videoComposition.instructions = @[passThroughInstruction]; 

    // If an image is given, then put that in the animation. 
    if (image != nil) { 

     // Layer that merges the video and image 
     CALayer *parentLayer = [CALayer layer]; 
     parentLayer.frame = CGRectMake(0, 0, crop.size.width, crop.size.height); 

     // Layer that renders the video. 
     CALayer *videoLayer = [CALayer layer]; 
     videoLayer.frame = CGRectMake(0, 0, crop.size.width, crop.size.height); 
     [parentLayer addSublayer:videoLayer]; 

     // Layer that renders flyerly image. 
     CALayer *imageLayer = [CALayer layer]; 
     imageLayer.frame = CGRectMake(0, 0, crop.size.width, crop.size.height); 
     imageLayer.contents = (id)image.CGImage; 
     [imageLayer setMasksToBounds:YES]; 

     [parentLayer addSublayer:imageLayer]; 

     // Setup the animation tool 
     videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; 
    } 

    // Now export the movie 
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality]; 
    exportSession.videoComposition = videoComposition; 

    // Export the URL 
    exportSession.outputURL = dest; 
    exportSession.outputFileType = AVFileTypeQuickTimeMovie; 
    exportSession.shouldOptimizeForNetworkUse = YES; 
    [exportSession exportAsynchronouslyWithCompletionHandler:^{ 
     callback(exportSession.status, exportSession.error); 
    }]; 
} 

Tôi gọi chức năng này từ AppDelegate.m

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{ 
     // Clean up any unfinished task business by marking where you 
     // stopped or ending the task outright. 
     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 

    // Start the long-running task and return immediately. 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

     // Do the work associated with the task, preferably in chunks. 
     [self goingToBg]; 

     [application endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }); 

    NSLog(@"backgroundTimeRemaining: %f", [[UIApplication sharedApplication] backgroundTimeRemaining]); 
} 
+1

Ở đây, Người dùng có thể chuyển đổi video Xếp & Play chúng với âm thanh trong máy nghe nhạc video sáp nhập -Link: https: //github.com/mehulparmar4ever/ConvertVideoReverse LƯU Ý: 1.User thể Đảo ngược Original Video. 2. Chuyển đổi âm thanh từ video 3.Thêm tệp âm thanh và video cùng nhau & phát chúng – Mehul

+0

hmm, ngay bây giờ tôi không ở trạng thái để hoàn nguyên mã của mình, tôi đang tìm kiếm bản sửa lỗi cho nó, không thay đổi thư viện :) –

Trả lời

7

Đã rất nhiều RND về vấn đề này, đã không tìm thấy giải pháp cho nó.

Bạn muốn chia sẻ một số liên kết, hy vọng nó sẽ giúp cộng đồng ngăn xếp nếu họ gặp vấn đề tương tự [yêu cầu].

link1: AVExportSession to run in background

Trích dẫn liên quan đến câu hỏi [sao chép từ trên LINK1]

Đáng buồn thay, kể từ AVAssetExportSession sử dụng gpu để làm một số của nó làm việc, nó không thể chạy ở chế độ nền nếu bạn đang sử dụng AVVideoComposition.

Link2: Starting AVAssetExportSession in the Background

Trích dẫn liên quan đến câu hỏi [sao chép từ trên Link2]

Bạn có thể bắt đầu AVAssetExportSession ở chế độ nền. Những hạn chế duy nhất trong AVFoundation để thực hiện công việc trong nền, đang sử dụng AVVideoCompositions hoặc AVMutableVideoCompositions. AVVideoCompositions đang sử dụng GPU, và GPU không thể được sử dụng ở chế độ nền

Url (s) cho các nhiệm vụ nền:

APPLE DEV URL

RAYWENDERLICH URL

Stack question

0

Quá đến bữa tiệc muộn, nếu bạn cập nhật cài đặt "Chế độ nền" trong khả năng của dự án thành lude Audio. Nó sẽ cho phép xuất khẩu.

Đây là mục đích để phát nhạc ở chế độ nền.

Nó phù hợp với tôi.

+0

Bạn có tìm thấy giải pháp thay thế cho điều này không? Ứng dụng của chúng tôi bị từ chối vì chúng tôi không sử dụng âm thanh nền – DennisA

Các vấn đề liên quan