1

UIImages 배열에서 비디오를 만들고 있습니다. 나는 그것을 성공적으로했다 & 모든 이미지는 비디오에 게재되고 있습니다. AVAssetExportSession을 사용하여 AVAssetExportSession을 사용할 때를 제외하고 작동하는 비디오를 내 보냅니다. videoComposition 속성 비디오는 첫 번째 이미지 만 표시합니다.AVAssetExportSession video 비디오의 모든 프레임을 표시하지 않는 비디오 구성

func mergeAudioVideoFiles(videoUrl:NSURL, audioUrl:NSURL)->NSURL 
{ 
    let mixComposition : AVMutableComposition = AVMutableComposition() 
    var mutableCompositionVideoTrack : [AVMutableCompositionTrack] = [] 
    var mutableCompositionAudioTrack : [AVMutableCompositionTrack] = [] 
    let totalVideoCompositionInstruction : AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction() 


    //start merge 

    let aVideoAsset : AVAsset = AVAsset(URL: videoUrl) 
    let aAudioAsset : AVAsset = AVAsset(URL: audioUrl) 

    mutableCompositionVideoTrack.append(mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)) 
    mutableCompositionAudioTrack.append(mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)) 

    let aVideoAssetTrack : AVAssetTrack = aVideoAsset.tracksWithMediaType(AVMediaTypeVideo)[0] 
    let aAudioAssetTrack : AVAssetTrack = aAudioAsset.tracksWithMediaType(AVMediaTypeAudio)[0] 
    do{ 
     try mutableCompositionVideoTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), ofTrack: aVideoAssetTrack, atTime: kCMTimeZero) 

     try mutableCompositionAudioTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), ofTrack: aAudioAssetTrack, atTime: kCMTimeZero)  
    }catch{ 

    } 
    print("\nslide duraition:\(CMTimeGetSeconds(aVideoAssetTrack.timeRange.duration))\n") 
    totalVideoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero,aVideoAssetTrack.timeRange.duration) 

    let mutableVideoComposition : AVMutableVideoComposition = AVMutableVideoComposition(propertiesOfAsset: aVideoAsset) 
    mutableVideoComposition.frameDuration = aVideoAssetTrack.timeRange.duration 
    mutableVideoComposition.renderSize = CGSizeMake(1280,720) 

    //find your video on this URl 
    let savePathUrl : NSURL = NSURL(fileURLWithPath: documentsPath.stringByAppendingPathComponent("pandorarofinalist.mov")) 

    // 4. Add subtitles (we call it theme) 
    let insertTime = kCMTimeZero 
    //let endTime = aVideoAssetTrack.timeRange.duration 
    //let range = self.totalFrameDuration 
    //let themeVideoComposition : AVMutableVideoComposition = AVMutableVideoComposition(propertiesOfAsset: aVideoAsset) 
    // 4.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation. 

    let videolayerInstruction : AVMutableVideoCompositionLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: aVideoAssetTrack) 
    totalVideoCompositionInstruction.layerInstructions = NSArray(array: [videolayerInstruction]) as! [AVVideoCompositionLayerInstruction] 
    mutableVideoComposition.instructions = NSArray(array: [totalVideoCompositionInstruction]) as! [AVVideoCompositionInstructionProtocol] 

    //mutableCompositionAudioTrack[0].preferredTransform 
    videolayerInstruction.setTransform(mutableCompositionVideoTrack[0].preferredTransform, atTime: insertTime) 
    //videolayerInstruction.setOpacity(0.0, atTime: endTime) 

    // 4.3 - Add instructions 


    // mutableVideoComposition.renderScale = 1.0 
    //themeVideoComposition.renderSize = CGSizeMake(aVideoAssetTrack.naturalSize.width, aVideoAssetTrack.naturalSize.height) 
    //themeVideoComposition.frameDuration = self.totalFrameDuration 

    // add text 

    let title = String("my video") 

    let titleLayer = CATextLayer() 
    titleLayer.string = title 
    titleLayer.frame = CGRect(x: 0, y: 0, width: aVideoAssetTrack.naturalSize.width, height: 100) 
    let fontName: CFStringRef = "Helvetica-Bold" 
    let fontSize = CGFloat(50) 
    titleLayer.font = CTFontCreateWithName(fontName, fontSize, nil) 
    titleLayer.alignmentMode = kCAAlignmentCenter 
    titleLayer.foregroundColor = UIColor.orangeColor().CGColor 

    let backgroundLayer = CALayer() 
    backgroundLayer.frame = CGRect(x: 0, y: 0, width: aVideoAssetTrack.naturalSize.width, height: aVideoAssetTrack.naturalSize.height) 
    backgroundLayer.masksToBounds = true 
    backgroundLayer.addSublayer(titleLayer) 

    // 2. set parent layer and video layer 

    let parentLayer = CALayer() 
    let videoLayer = CALayer() 
    parentLayer.frame = CGRect(x: 0, y: 0, width: aVideoAssetTrack.naturalSize.width, height: aVideoAssetTrack.naturalSize.height) 
    videoLayer.frame = CGRect(x: 0, y: 0, width: aVideoAssetTrack.naturalSize.width, height: aVideoAssetTrack.naturalSize.height) 
    parentLayer.addSublayer(videoLayer) 
    parentLayer.addSublayer(backgroundLayer) 

    //backgroundLayer.opacity = 1.0 

    // 3. make animation 

    mutableVideoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer) 

    // Remove the file if it already exists (merger does not overwrite) 

    do{ 
     let fileManager = NSFileManager.defaultManager() 
     try fileManager.removeItemAtURL(savePathUrl) 
    }catch{ 
    } 

    let assetExport: AVAssetExportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)! 
    assetExport.outputFileType = AVFileTypeMPEG4 
    assetExport.outputURL = savePathUrl 
    assetExport.shouldOptimizeForNetworkUse = true 
    assetExport.videoComposition = mutableVideoComposition 

    assetExport.exportAsynchronouslyWithCompletionHandler {() -> Void in 
     switch assetExport.status { 

     case AVAssetExportSessionStatus.Completed: 

      PHPhotoLibrary.sharedPhotoLibrary().performChanges({ 
       PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(savePathUrl) 
      }) { success, error in 
       if !success { 
        print("Error saving video: \(error)") 
       } 
      } 

      //Uncomment this if u want to store your video in asset 

      //let assetsLib = ALAssetsLibrary() 
      //assetsLib.writeVideoAtPathToSavedPhotosAlbum(savePathUrl, completionBlock: nil) 

      print("success") 
     case AVAssetExportSessionStatus.Failed: 
      print("failed \(assetExport.error)") 
     case AVAssetExportSessionStatus.Cancelled: 
      print("cancelled \(assetExport.error)") 
     default: 
      print("complete") 
     } 
    } 

    return savePathUrl 
} 

문제는 내가이 줄을 생략하면 출력 비디오가 잘입니다 라인 assetExport.videoComposition = mutableVideoComposition입니다 : 여기 내 코드입니다. 그러나이 줄을 추가하면 출력 비디오는 내가 비디오에 추가 한 첫 번째 이미지 만 보여줍니다. 나는 내가 CALayer로 추가 한 비디오에 제목 텍스트를 추가하고 있기 때문에 videoComposition을 설정해야합니다. 내 프로젝트에 신속한 2.2를 사용하고 있습니다. 어떤 도움을 주시겠습니까? 미리 감사드립니다.

+0

해결책을 찾았습니까? – Sam

+0

이것은 AVVideoCompositionCoreAnimationTool의 버그입니다.이 게시물 및 모든 관련 게시물을 확인하십시오. http://stackoverflow.com/search?tab=newest&q=swift%20AVAssetWriter – Sam

+0

그러나 솔루션을 구현할 수 없었습니다. – Sam

답변

2

나는 문제가이 줄을 믿습니다 :

mutableVideoComposition.frameDuration = aVideoAssetTrack.timeRange.duration

frameDuration는 비디오에서 비디오의하지 총 지속 시간을 단일 프레임의 기간을 나타냅니다 예정이다. 위의 줄은 비디오의 한 프레임이 원본 비디오 트랙의 지속 시간을 지속하도록하므로 한 프레임 만 볼 수 있습니다. 마치 정지 이미지 인 것처럼 보입니다. 초당 30 프레임의 동영상을

, 당신은 다음과 같이 두 번째의 1/30로 frameDuration을 설정해야합니다

mutableVideoComposition.frameDuration = CMTime(value: 1, timescale: 30)


경고 :주의 다른 초기화 방법을 사용하지 CMTime(seconds: 1.0, preferredTimescale: 30) 왜냐하면 이렇게하면 frameDuration이 1 초가 될 것이기 때문입니다.

관련 문제