Как экспортировать произвольный сегмент видео? Ошибка Operation Stopped при экспорте последних X секунд видео

Цель состоит в том, чтобы экспортировать произвольный сегмент некоторого видео (например, среднюю треть, последнюю половину), но AVAssetExportSession удается только в том случае, если отправной точкой является начало видео.

Если cmStartTime не равно 0, AVAssetExportSession завершается с ошибкой:

Ошибка: необязательно (домен ошибки = AVFoundationErrorDomain Code = -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
    }

person Crashalot    schedule 15.06.2016    source источник


Ответы (1)


Проблема возникла из-за непонимания CMTimeRangeMake и insertTimeRange.

Второе значение CMTimeRangeMake должно быть продолжительностью клипа, а не временем окончания. Поэтому, если ваше время начала составляет 5 секунд, а клип длится 10 секунд, второе значение должно быть 10, а не 15.

Параметр atTime параметра insertTimeRange должен быть равен kCMTimeZero, так как целью является создание нового клипа. Другими словами, это значение указывает, где в новой дорожке вставить клип из исходной дорожки.

person Crashalot    schedule 16.06.2016