ScaleTimeRange только части видео

Метод scaleTimeRange(timeRange: CMTimeRange, toDuration duration: CMTime) работает очень хорошо, если вы хотите применить эффект замедленного движения к видео.

Но я заметил, что это работает, только если применяется ко всей продолжительности видео. Если произвольный timeRange, например. передается CMTimeRangeMake(_ start: 2, duration: 3) , метод вообще не работает. т. е. когда видео mp4 экспортируется, оно не имеет желаемого эффекта замедленного движения (от 0:00:02 до 0:00:05).

Вопрос 1) Можно ли применить этот метод scaleTimeRange только к части видео? Если да, то как это можно сделать?

Q2) Если нет, то как этот эффект замедления можно применить только к части видео? Есть ли другой способ?

КОД :

var asset: AVAsset?


func  setupAsset(){

let videoAsset = AVURLAsset(url: Bundle.main.url(forResource: "Sample", withExtension: "mp4")!)

let comp = AVMutableComposition()

let videoAssetSourceTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo).first! as AVAssetTrack


let videoCompositionTrack = comp.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)


do {

    try videoCompositionTrack.insertTimeRange(
        CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(9 , 600)),
        of: videoAssetSourceTrack,
        at: kCMTimeZero)


    let videoScaleFactor = Int64(3.0)
    let videoDuration: CMTime = videoAsset.duration



    let tstStartTime = CMTime(value: 2, timescale: videoDuration.timescale)
    let tstDuration =  CMTime(value: 1 , timescale: videoDuration.timescale)

    //1.  Applies slow motion correctly (to entire video)

    videoCompositionTrack.scaleTimeRange(CMTimeRangeMake(kCMTimeZero , videoDuration), toDuration: CMTimeMake(videoDuration.value * videoScaleFactor, videoDuration.timescale))

    //2. Replace with 1 , the exported video plays as is with no slow motion effect

    videoCompositionTrack.scaleTimeRange(CMTimeRangeMake(kCMTimeZero , tstDuration), toDuration: CMTimeMake(tstDuration.value * videoScaleFactor, videoDuration.timescale))

    // 3. Replace with 1, unexpected behaviour : video only displays first frame for CMTimeMakes's value then proceeds to play video normally.
    videoCompositionTrack.scaleTimeRange(CMTimeRangeMake(tstStartTime , tstDuration), toDuration: CMTimeMake(tstDuration.value * videoScaleFactor, videoDuration.timescale))



     videoCompositionTrack.preferredTransform = videoAssetSourceTrack.preferredTransform



}catch { print(error) }

asset = comp
}

person Community    schedule 20.01.2017    source источник
comment
В чем именно проблема, кажется, что метод вообще не работает?   -  person shallowThought    schedule 20.01.2017
comment
Видео успешно сохранено, однако эффекта замедления нет. Экспортированный файл mp4 идентичен исходному файлу mp4 с той же частотой кадров.   -  person    schedule 20.01.2017
comment
Что такое значение CMTimes? Можете ли вы опубликовать соответствующий код, пожалуйста?   -  person shallowThought    schedule 20.01.2017
comment
Я обновил вопрос. Пожалуйста, посмотрите.   -  person    schedule 20.01.2017
comment
Если вы сделали это, пожалуйста, поделитесь кодом или подсказкой.   -  person TheTiger    schedule 06.02.2018


Ответы (1)


Я предполагаю, что он работает «правильно», но часть видео, которую вы замедляете, намного меньше, чем вы ожидаете.

CMTime — это очень необычная структура данных, поэтому может быть очень сложно понять ее. Какое значение videoDuration.timescale вы используете для построения переменных tstStartTime и tstDuration? Чем больше значение шкалы времени, тем меньшая часть времени представлена ​​значением CMTime.

Например, если шкала времени равна 4, то CMTime(value: 2, timescale: 4) представляет 2/4 секунд или полсекунды.

Для получения дополнительной информации см. документацию для CMTime: https://developer.apple.com/reference/coremedia/1669288-cmtime

person Dave Weston    schedule 22.01.2017
comment
Значение videoDuration.timescale равно 600. У меня есть небольшое представление о том, что делает timeScale, но я видел код, где это значение равно 90000, и это очень сбивает с толку, потому что я не знаю, зачем нужно такое высокое значение. Это пример приложения StopNGo от Apple frameDuration = CMTimeMakeWithSeconds = CMTimeMake(1.0/5/0 , 90000) //5 кадров в секунду — пять снимков будут равняться 1 секунде видео. - person ; 23.01.2017
comment
Я не уверен в конкретной причине, по которой они выбрали шкалу времени 90000 для этого образца, но причина, по которой CMTime работает так, заключается в том, чтобы обеспечить чрезвычайно высокую точность в широком диапазоне без ошибки округления. Вот сообщение в блоге, в котором делается попытка объяснить это более подробно: warrenmoore.net/understanding-cmtime - person Dave Weston; 23.01.2017
comment
Спасибо, что указали на проблему. Я предполагал, что scaleTimeRange можно использовать только для всего видео, а не для его сегмента, но, возможно, мне нужно углубить свое понимание CMTime. - person ; 23.01.2017