그것은 조금 짜증나,하지만 난 당신이 품질을 잃고 싶지 않는 경우가 AVComposition
에서 비디오를 다시 만들어야합니다 생각합니다. 다른 방법이 있는지 알고 싶지만 이것이 내가 생각해 낸 것입니다. 기술적으로 AVAssetExportSession을 통해 비디오를 내보낼 수 있지만 패스 스루 (PassThrough) 품질을 사용하면 동일한 비디오 파일이 만들어 지므로 느리게 움직이지 않습니다. 품질을 떨어 뜨리는 코드 변환이 필요합니다 (AFAIK 해당 솔루션의 경우 Issue playing slow-mo AVAsset in AVPlayer 참조) .
가장 먼저해야 할 일은 원본 미디어의 원래 시간 매핑 개체를 가져 오는 것입니다. 원래 미디어 (문서 디렉토리에 앉아 하나)의 timeMappings이 있으면
let options = PHVideoRequestOptions()
options.version = PHVideoRequestOptionsVersion.current
options.deliveryMode = .highQualityFormat
PHImageManager().requestAVAsset(forVideo: phAsset, options: options, resultHandler: { (avAsset, mix, info) in
guard let avAsset = avAsset else { return }
let originalTimeMaps = avAsset.tracks(withMediaType: AVMediaTypeVideo)
.first?
.segments
.flatMap { $0.timeMapping } ?? []
}
, 당신은 그 매체의 URL과 원래 CMTimeMapping 객체에 전달할 수 있습니다 당신이 싶습니다 그래서 같은 것을 당신은 할 수있다 재창조해라. 그런 다음 AVPlayer에서 재생할 준비가 된 새 AVComposition을 만듭니다. 이 유사한 클래스가 필요합니다
class CompositionMapper {
let url: URL
let timeMappings: [CMTimeMapping]
init(for url: URL, with timeMappings: [CMTimeMapping]) {
self.url = url
self.timeMappings = timeMappings
}
init(with asset: AVAsset, and timeMappings: [CMTimeMapping]) {
guard let asset = asset as? AVURLAsset else {
print("cannot get a base URL from this asset.")
fatalError()
}
self.timeMappings = timeMappings
self.url = asset.url
}
func compose() -> AVComposition {
let composition = AVMutableComposition(urlAssetInitializationOptions: [AVURLAssetPreferPreciseDurationAndTimingKey: true])
let emptyTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
let audioTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)
let asset = AVAsset(url: url)
guard let videoAssetTrack = asset.tracks(withMediaType: AVMediaTypeVideo).first else { return composition }
var segments: [AVCompositionTrackSegment] = []
for map in timeMappings {
let segment = AVCompositionTrackSegment(url: url, trackID: kCMPersistentTrackID_Invalid, sourceTimeRange: map.source, targetTimeRange: map.target)
segments.append(segment)
}
emptyTrack.preferredTransform = videoAssetTrack.preferredTransform
emptyTrack.segments = segments
if let _ = asset.tracks(withMediaType: AVMediaTypeVideo).first {
audioTrack.segments = segments
}
return composition.copy() as! AVComposition
}
그런 다음 CMTimeMapping
객체를 존중해야 당신에게 AVPlayer
에서 재생할 준비가있는 AVComposition
를 제공하려면 CompositionMapper
클래스의 compose()
기능을 사용할 수 있습니다 당신 들어갔다.
let compositionMapper = CompositionMapper(for: someAVAssetURL, with: originalTimeMaps)
let mappedComposition = compositionMapper.compose()
let playerItem = AVPlayerItem(asset: mappedComposition)
let player = AVPlayer(playerItem: playerItem)
playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmVarispeed
이것을 Objective-C로 변환하는 데 도움이 필요하시면 알려주세요.하지만 비교적 간단합니다.
가능한 [iOS AVPlayer 속도 저하] (https://stackoverflow.com/questions/37249146/ios-avplayer-slow-down) – the4kman