我有一段带有这些规格的视频
在实验中,我在每一个其他帧上执行了一个removeTimeRange(range : CMTimeRange) (总帧= 4225)。这将导致视频速度提高2倍,因此持续时间为1:30。
然而,当我导出视频时,视频变得大12倍,即325 it .This是有意义的,因为这种技术是将视频分解成大约2112片段并将其重新拼接在一起。显然,这样做的话,单个帧之间的压缩就会丢失,从而导致巨大的尺寸。
当播放AVPlayer时,这会导致视频中的口吃,因此性能很差。
问题:我如何在拼接帧的同时应用某种压缩,这样视频就可以播放得很流畅,而且体积也更小?
我只想找个正确的方向。谢谢!
码
1)从资产创建AVMutableComposition &配置它
func configureAssets(){
let options = [AVURLAssetPreferPreciseDurationAndTimingKey : "true"]
let videoAsset = AVURLAsset(url: Bundle.main.url(forResource: "Push", withExtension: "mp4")! , options : options)
let videoAssetSourceTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo).first! as AVAssetTrack
let comp = AVMutableComposition()
let videoCompositionTrack = comp.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
do {
try videoCompositionTrack.insertTimeRange(
CMTimeRangeMake(kCMTimeZero, videoAsset.duration),
of: videoAssetSourceTrack,
at: kCMTimeZero)
deleteSomeFrames(from: comp)
videoCompositionTrack.preferredTransform = videoAssetSourceTrack.preferredTransform
}catch { print(error) }
asset = comp }2)删除所有其他帧。
func deleteSomeFrames(from asset : AVMutableComposition){
let fps = Int32(asset.tracks(withMediaType: AVMediaTypeVideo).first!.nominalFrameRate)
let sumTime = Int32(asset.duration.value) / asset.duration.timescale;
let totalFrames = sumTime * fps
let totalTime = Float(CMTimeGetSeconds(asset.duration))
let frameDuration = Double(totalTime / Float(totalFrames))
let frameTime = CMTime(seconds: frameDuration, preferredTimescale: 1000)
for frame in Swift.stride(from: 0, to: totalFrames, by: 2){
let timing = CMTimeMultiplyByFloat64(frameTime, Float64(frame))
print("Asset Duration = \(CMTimeGetSeconds(asset.duration))")
print("")
let timeRange = CMTimeRange(start: timing, duration : frameTime)
asset.removeTimeRange(timeRange)
}
print("duration after time removed = \(CMTimeGetSeconds(asset.duration))")
}3)保存文件
func createFileFromAsset(_ asset: AVAsset){
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL
let filePath = documentsDirectory.appendingPathComponent("rendered-vid.mp4")
if let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality){
exportSession.outputURL = filePath
exportSession.shouldOptimizeForNetworkUse = true
exportSession.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration)
exportSession.outputFileType = AVFileTypeQuickTimeMovie
exportSession.exportAsynchronously {
print("finished: \(filePath) : \(exportSession.status.rawValue) ")
if exportSession.status.rawValue == 4{
print("Export failed -> Reason: \(exportSession.error!.localizedDescription))")
print(exportSession.error!)
}
}}}4)最后更新ViewController播放新的作文!
override func viewDidLoad() {
super.viewDidLoad()
// Create the AVPlayer and play the composition
assetConfig.configureAssets()
let snapshot : AVComposition = assetConfig.asset as! AVComposition
let playerItem = AVPlayerItem(asset : snapshot)
player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = CGRect(x : 0, y : 0, width : self.view.frame.width , height : self.view.frame.height)
self.view.layer.addSublayer(playerLayer)
player?.play()
}发布于 2017-03-13 08:07:22
如果您正在使用AVMutableComposition,您将注意到每个组合可能包含一个或多个AVCompositionTrack(or AVMutableCompositionTrack),编辑作文的最佳方法是操作每个轨道,而不是整个组合。
但是,如果您的目的是加快您的视频的速度,编辑轨道将是不必要的。
所以我会尽我所能告诉你我对你问题的了解
关于播放视频口吃
口吃的可能原因
请注意,您使用的是removeTimeRange(range: CMTimeRange)方法,此方法将删除组合是的timeRange,但不会自动填充每个时间范围的空值。
Visualize Example
[F stand for Frame,E stand for Empty]
org_video --> F-F-F-F-F-F-F-F...
after remove time range, the composition will be like this
after_video --> F-E-F-E-F-E-F-E...
and you might think that the video will be like this
target_video --> F-F-F-F...这是在播放过程中口吃的最可能的原因。
建议解决方案
因此,如果您想要缩短视频,使其速度更快/更慢,您可能需要使用方法scaleTimeRange:(CMTimeRange) toDuration:(CMTime)。
Example
AVMutableComposition * project;//if this video is 200s
//Scale
project.scaleTimeRange:CMTimeRangeMake(kCMTimeZero, project.duration) toDuration:CMTimeMakeWithSeconds(100,kCMTimeMaxTimescale)这种方法是使视频更快/更慢。
关于文件大小
视频文件的大小可能会受到比特率和格式类型的影响,如果使用H.264,导致大小放大的最可能的原因将是比特率。
在您的代码中,您正在使用AVAssetExportSession
AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality你在我自己的应用项目中给出了AVAssetExportPresetHighestQuality预置,在我使用这个预置后,视频的比特率将是20~30 30Mbps,不管你的源视频的比特率如何。而且,使用苹果的预置将不允许你手动设定比特率,所以。
可能解决办法
还有一个名为SDAVAssetExportSession的第三部分工具,这个会话将允许您完全配置导出会话,您可能希望尝试学习有关自定义导出会话预置的代码。
我现在可以告诉你的是。希望能帮助:>
https://stackoverflow.com/questions/42413171
复制相似问题