[英]How to export arbitrary segment of video? “Operation Stopped” error when exporting last X seconds of video
The goal is to export an arbitrary segment of some video (eg, middle third, last half), but AVAssetExportSession
only succeeds if the starting point is the start of the video. 目标是导出某些视频的任意片段(例如,中间三分之一,最后一半),但是
AVAssetExportSession
仅在起点是视频的起点时成功。
If cmStartTime
is not 0, AVAssetExportSession
fails with this error: 如果
cmStartTime
不为0,则AVAssetExportSession
失败,并显示以下错误:
Failed: Optional(Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo=0x175872d00 {NSLocalizedDescription=Operation Stopped, NSLocalizedFailureReason=The video could not be composed.}).
失败:可选(错误域= AVFoundationErrorDomain代码= -11841“操作已停止” UserInfo = 0x175872d00 {NSLocalizedDescription =操作已停止,NSLocalizedFailureReason =无法合成视频。})。
// Create main composition & its tracks
let mainComposition = AVMutableComposition()
let compositionVideoTrack = mainComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
let compositionAudioTrack = mainComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
// Get source video & audio tracks
let videoURL = NSURL(fileURLWithPath: fileURL)
let videoAsset = AVURLAsset(URL: videoURL, options: nil)
let sourceVideoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0]
let sourceAudioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0]
// Define time values for video
let timescale = Int32(600)
let cmStartTime = CMTimeMake(Int64(CGFloat(0.5) * CGFloat(timescale)), timescale)
let cmEndTime = CMTimeMake(10, 1)
let timeRange = CMTimeRangeMake(cmStartTime, cmEndTime)
// Add source tracks to composition
do {
try compositionVideoTrack.insertTimeRange(timeRange, ofTrack: sourceVideoTrack, atTime: cmStartTime)
try compositionAudioTrack.insertTimeRange(timeRange, ofTrack: sourceAudioTrack, atTime: cmStartTime)
} catch {
printError("Error with insertTimeRange while exporting video: \(error)")
}
// Create video composition
let renderSize = compositionVideoTrack.naturalSize
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = renderSize
videoComposition.frameDuration = CMTimeMake(Int64(1), Int32(frameRate))
// Add layer instruction to video composition
...
// Apply effects to video
...
// Define export URL
let exportPath = getUniqueTempPath(gMP4File)
let exportURL = NSURL(fileURLWithPath: exportPath)
// Create exporter
let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)!
exporter.videoComposition = videoComposition
exporter.outputFileType = AVFileTypeMPEG4
exporter.outputURL = exportURL
exporter.shouldOptimizeForNetworkUse = true
exporters.append(exporter)
// Export video
exporter.exportAsynchronouslyWithCompletionHandler() {
// Finish stuff
}
The problem arose from not understanding CMTimeRangeMake
and insertTimeRange
. 问题来自于不了解
CMTimeRangeMake
和insertTimeRange
。
The second value of CMTimeRangeMake
should be the clip duration, not the end time. CMTimeRangeMake
的第二个值应该是剪辑的持续时间,而不是结束时间。 So if your start time is the 5 second mark, and the clip lasts 10 seconds, the second value should be 10, not 15. 因此,如果您的开始时间是5秒标记,并且剪辑持续10秒,则第二个值应该是10,而不是15。
The atTime
parameter of insertTimeRange
should be kCMTimeZero
since the goal is to create a new clip. 该
atTime
的参数insertTimeRange
应kCMTimeZero
,因为我们的目标是创建一个新的剪辑。 In other words, this value says where in the new track to insert the clip from the source track. 换句话说,此值表示要在新轨道中从源轨道插入剪辑的位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.