gpt4 book ai didi

ios - 视频的 scaleTimeRange 防止在 Xcode 7 上以 Swift 2.0+ 导出视频

转载 作者:搜寻专家 更新时间:2023-11-01 05:38:13 30 4
gpt4 key购买 nike

我正在使用 AVFoundation 在自定义相机应用程序中录制视频。以下代码成功地从 previewView 捕获视频并将其转换为保存到设备照片库的视频 Assets 。我想让应用程序使用效果将视频转换为慢动作视频,并且听人说 AVMutableCompositionscaleTimeRange 可以做到这一点。但是当我尝试实现如下面的代码所示时,视频没有导出,效果也不是慢动作。

func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {

if(error != nil){
print(error)
}

self.lockInterfaceRotation = false

let backgroundRecordId: UIBackgroundTaskIdentifier = self.backgroundRecordId
self.backgroundRecordId = UIBackgroundTaskInvalid

//create mutable composition of video and slow it down

let videoAsset = AVURLAsset(URL: outputFileURL, options: nil)
let mixComposition = AVMutableComposition()
let videoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let audioTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))

let sourceVideoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0]
let sourceAudioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0]
do{
try videoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: sourceVideoTrack, atTime: kCMTimeZero)

try audioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: sourceAudioTrack, atTime: kCMTimeZero)
}catch _ {
print("ERROR could not insert time range")
return
}

/* ** THE PART THAT ISN'T WORKING - When I add this section everything breaks **
//slow video down for slow mo effect
let videoDuration = videoAsset.duration;
let videoScaleFactor = 2 * videoDuration.value

videoTrack.scaleTimeRange(CMTimeRangeMake(kCMTimeZero, videoDuration), toDuration: CMTimeMake(videoScaleFactor, videoDuration.timescale))
*/

// Make mutable combination
// -- Create instruction
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
instruction.layerInstructions = [videoLayerInstruction]

let mutableComposition = AVMutableVideoComposition()
mutableComposition.renderSize = videoTrack.naturalSize
mutableComposition.frameDuration = CMTimeMake(1, 20)
mutableComposition.instructions = [instruction]

// -- Get path
let fileName = "/editedVideo-\(arc4random() % 10000).mp4"
let allPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docsPath = allPaths[0] as NSString
let exportPath = docsPath.stringByAppendingFormat(fileName)
let exportUrl = NSURL.fileURLWithPath(exportPath as String)

print("Tracks before export: \(mixComposition.tracks.count). File URL: \(exportUrl)")

// -- Remove old video if exists
if NSFileManager.defaultManager().fileExistsAtPath(exportPath as String) {
print("Deleting existing file\n")
do{
try NSFileManager.defaultManager().removeItemAtPath(exportPath as String)
}catch _ {
print("Error deleting old video file")
}

}

// -- Create exporter
let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
exporter!.videoComposition = mutableComposition
exporter!.outputFileType = AVFileTypeMPEG4
exporter!.outputURL = exportUrl
exporter!.shouldOptimizeForNetworkUse = true

// -- Export video
exporter!.exportAsynchronouslyWithCompletionHandler({
self.exportDidFinish(exporter!)
})

}

func exportDidFinish(exporter: AVAssetExportSession) {

// Save video to photo album
let assetLibrary = ALAssetsLibrary()
assetLibrary.writeVideoAtPathToSavedPhotosAlbum(exporter.outputURL, completionBlock: {(url: NSURL!, error: NSError!) in
print("Saved video to album \(exporter.outputURL)")
if (error != nil) {
print("Error saving video")
}
})

// Check asset tracks
print("SUCCESS exporting video")
}

任何想法将不胜感激!谢谢

最佳答案

我最终通过取出音频并执行以下操作使其正常工作:

let videoAsset = AVURLAsset(URL: NSURL(fileURLWithPath: self.pathToMovie), options: nil)
let mixComposition = AVMutableComposition()
let compositionVideoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)

do {
try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: (videoAsset.tracksWithMediaType(AVMediaTypeVideo).first)!, atTime: kCMTimeZero)
} catch {
print("handle insert error")
return
}

let videoDuration = videoAsset.duration

//slow down the video to half speed (change multiplier to desired value)
let finalTimeScale : Int64 = videoDuration.value * 2

compositionVideoTrack.scaleTimeRange(CMTimeRangeMake(kCMTimeZero, videoDuration), toDuration: CMTimeMake(finalTimeScale, videoDuration.timescale))

let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let finalURL = documentsURL.URLByAppendingPathComponent("what_you_want_to_call_your_video.mp4")

//make sure no other file where this one will be saved
let manager = NSFileManager()
do {
try manager.removeItemAtPath(finalURL.path!)
} catch {
print("file doesn't exist or couldn't remove file at path")
}

let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
exporter!.outputURL = finalURL
exporter!.outputFileType = AVFileTypeMPEG4 //AVFileTypeQuickTimeMovie, whatever format you want that AVFoundation does
exporter!.exportAsynchronouslyWithCompletionHandler({
switch exporter!.status{
case AVAssetExportSessionStatus.Failed:
print("failed \(exporter!.error)")

dispatch_async(dispatch_get_main_queue(), {

print("Error saving video is \(exporter!.error!.description)")

//Show an alert
let alertController: UIAlertController = UIAlertController(title: "Error Exporting Video", message: "\(exporter!.error) \(exporter!.error!.description). Please try again", preferredStyle: .Alert)

//Create and add the Cancel action
let okayAction: UIAlertAction = UIAlertAction(title: "Okay", style: .Cancel) { action -> Void in
//Do some stuff
}
alertController.addAction(okayAction)

//Present the AlertController
self.presentViewController(alertController, animated: true, completion: nil)
})

case AVAssetExportSessionStatus.Cancelled:
print("cancelled \(exporter!.error)")

dispatch_async(dispatch_get_main_queue(), {

print("Error saving video is \(exporter!.error!.description)")

//Show an alert
let alertController: UIAlertController = UIAlertController(title: "Error Exporting Video", message: "\(exporter!.error) \(exporter!.error!.description). Please try again", preferredStyle: .Alert)

//Create and add the Cancel action
let okayAction: UIAlertAction = UIAlertAction(title: "Okay", style: .Cancel) { action -> Void in
//Do some stuff
}
alertController.addAction(okayAction)

//Present the AlertController
self.presentViewController(alertController, animated: true, completion: nil)
})
default:
print("complete, now presenting confirmation")

dispatch_async(dispatch_get_main_queue(), {

//everything is done, do what you want to do now that video is created
})
}

})

关于ios - 视频的 scaleTimeRange 防止在 Xcode 7 上以 Swift 2.0+ 导出视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34365266/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com