Ios 快速压缩视频文件
所以,现在我用这个来压缩视频:Ios 快速压缩视频文件,ios,swift,xcode,video,avassetexportsession,Ios,Swift,Xcode,Video,Avassetexportsession,所以,现在我用这个来压缩视频: func compressVideo(inputURL: NSURL, outputURL: NSURL, handler:(session: AVAssetExportSession)-> Void) { let urlAsset = AVURLAsset(URL: inputURL, options: nil) let exportSession = AVAssetExportSession(asset: url
func compressVideo(inputURL: NSURL, outputURL: NSURL, handler:(session: AVAssetExportSession)-> Void)
{
let urlAsset = AVURLAsset(URL: inputURL, options: nil)
let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality)
exportSession!.outputURL = outputURL
exportSession!.outputFileType = AVFileTypeQuickTimeMovie
exportSession!.shouldOptimizeForNetworkUse = true
exportSession!.exportAsynchronouslyWithCompletionHandler { () -> Void in
handler(session: exportSession!)
}
}
当我在2秒内录制视频时,文件大小为4,3 MB,当我在6秒内录制视频时,文件大小为9,3 MB
减少大小的任何提示?此扩展侧重于将其导出到较低质量的设置(在本例中为中等质量),并使用
mp4
容器,而不是iOS喜欢的mov
容器。这可能会导致质量下降,但在微调输出时,您可以尝试使用更高的输出设置和不同的格式
extension PreviewVideoViewController: AVCaptureFileOutputRecordingDelegate {
func fileOutput(_ output: AVCaptureFileOutput,
didFinishRecordingTo outputFileURL: URL,
from connections: [AVCaptureConnection],
error: Error?) {
guard let data = try? Data(contentsOf: outputFileURL) else {
return
}
print("File size before compression: \(Double(data.count / 1048576)) mb")
let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + UUID().uuidString + ".mp4")
compressVideo(inputURL: outputFileURL as URL,
outputURL: compressedURL) { exportSession in
guard let session = exportSession else {
return
}
switch session.status {
case .unknown:
break
case .waiting:
break
case .exporting:
break
case .completed:
guard let compressedData = try? Data(contentsOf: compressedURL) else {
return
}
print("File size after compression: \(Double(compressedData.count / 1048576)) mb")
case .failed:
break
case .cancelled:
break
}
}
}
func compressVideo(inputURL: URL,
outputURL: URL,
handler:@escaping (_ exportSession: AVAssetExportSession?) -> Void) {
let urlAsset = AVURLAsset(url: inputURL, options: nil)
guard let exportSession = AVAssetExportSession(asset: urlAsset,
presetName: AVAssetExportPresetMediumQuality) else {
handler(nil)
return
}
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
exportSession.exportAsynchronously {
handler(exportSession)
}
}
}
//使用具有动态比特率的sdavasetexportsession库
func aVodzLatestVideoCompressor(inputURL:URL,aOutputURL:URL,aStartTime:Float,aEndTime:Float){
让sizeVideo:Float=inputURL.verboseFileSizeInMB()
如果sizeVideo<5.0{
DispatchQueue.main.async{
//self.directsendVideowithoutcopressor()
}
返回
}
让startTime=CMTime(秒数:双倍(aStartTime),首选时间刻度:1000)
让endTime=CMTime(秒:双精度(aEndTime),首选时间刻度:1000)
let timeRange=CMTimeRange(开始:开始时间,结束:结束时间)
让anAsset=avurlaste(url:inputURL,选项:nil)
guard let videoTrack=anAsset.tracks(withMediaType:AVMediaType.video)。首先是{return}
变量含水率:浮动=0.0
var duration=anaset.duration
让totalSeconds=Int(CMTimeGetSeconds(持续时间))
打印(“持续时间-\(持续时间)-总秒数-\(总秒数)”)
var比特率=最小值(aQuality,videoTrack.EstimatedDataate)
让landscap=self.isLandScapVideo(afileURL:inputURL)
var originalWidth=videoTrack.naturalSize.width
var originalHeight=videoTrack.naturalSize.height
打印(“原始宽度-\(原始宽度)原始高度-\(原始高度)”)
而(原始宽度>=1920 | |原始高度>=1920){
原始宽度=原始宽度/2
原始高度=原始高度/2
}
var setWidth=Int(原始宽度)
var setlHeight=Int(原始高度)
如果sizeVideo<10.0{
//压缩质量高:
setWidth=Int(原始宽度)
设置高度=整数(原始高度)
水性=浮动(设置宽度*设置高度*20)
比特率=最小值(aQuality,videoTrack.EstimatedDataate)
}否则,如果sizeVideo<20.0{
//压缩\质量\介质:
如果总秒数>35{
setWidth=Int(原始宽度/2.7)
设置高度=整数(原始高度/2.7)
}否则,如果总秒数>25{
setWidth=Int(原始宽度/2.3)
设置高度=整数(原始高度/2.3)
}否则{
setWidth=Int(原始宽度/2.0)
设置高度=整数(原始高度/2.0)
}
水性=浮动(设置宽度*设置高度*10)
比特率=最小值(aQuality,videoTrack.EstimatedDataate)
}否则,如果sizeVideo<30.0{
//压缩\质量\介质:
如果总秒数>35{
setWidth=Int(原始宽度/3)
设置高度=整数(原始高度/3)
}否则,如果总秒数>20{
setWidth=Int(原始宽度/2.5)
设置高度=整数(原始高度/2.5)
}否则{
setWidth=Int(原始宽度/2.0)
设置高度=整数(原始高度/2.0)
}
水性=浮动(设置宽度*设置高度*10)
比特率=最小值(aQuality,videoTrack.EstimatedDataate)
}否则{
如果总秒数>35{
setWidth=Int(原始宽度/3.0)
设置高度=整数(原始高度/3.0)
}否则,如果总秒数>25{
setWidth=Int(原始宽度/2.5)
设置高度=整数(原始高度/2.5)
}否则{
setWidth=Int(原始宽度/2.0)
设置高度=整数(原始高度/2.0)
}
水性=浮动(设置宽度*设置高度*10)
比特率=最小值(aQuality,videoTrack.EstimatedDataate)
}
印刷品(“水性”)
印刷(浮法(水性))
打印(“比特率”)
打印(浮动(比特率))
let encoder=sdavasetexportsession(资产:anaset)
编码器?.shouldOptimizationForNetworkUse=true
编码器?时间范围=时间范围
编码器?.outputFileType=AVFileType.mp4.rawValue
编码器?.outputURL=AOoutputURL
//960 X 540、1280*720、1920*1080//尺寸缩减参数
编码器?视频设置=[
AVVideoCodeKey:AVVideoCodeType.h264,
AVVideoWidthKey:landscap?NSNumber(值:1280):NSNumber(值:720),
AVVideoHeightKey:landscap?NSNumber(值:720):NSNumber(值:1280),
AVVideoCompressionProperties键:[
AVVideoAverageBitRateKey:NSNumber(值:比特率),
AVVideoProfileLevelKey:AVVideoProfileLevelH264高40
]
]
编码器?音频设置=[
AVFormatIDKey:NSNumber(值:kAudioFormatMPEG4AAC),
AVNumberOfChannelsKey:NSNumber(值:2),
AVSampleRateKey:NSNumber(值:44100),
AVEncoderBitRateKey:NSNumber(值:128000)
]
编码器?.exportAsyn
func convertVideo(phAsset : PHAsset){
PHImageManager.default().requestAVAsset(forVideo: phAsset, options: PHVideoRequestOptions(), resultHandler: { (asset, audioMix, info) -> Void in
if let asset = asset as? AVURLAsset {
do {
let videoData = try Data.init(contentsOf: asset.url)
print(asset.url)
self.orginalVideo = asset.url
print("File size before compression: \(Double(videoData.count / 1048576)) mb")
let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".MP4")
print(compressedURL)
self.compressVideo(inputURL: asset.url , outputURL: compressedURL) { (exportSession) in
guard let session = exportSession else {
return
}
switch session.status {
case .unknown:
print("unknown")
break
case .waiting:
print("waiting")
break
case .exporting:
print("exporting")
break
case .completed:
do {
let compressedData = try Data.init(contentsOf: compressedURL)
self.compressVideo = compressedURL
print(compressedData)
print("File size AFTER compression: \(Double(compressedData.count / 1048576)) mb")
}
catch{
print(error)
}
case .failed:
print("failed")
break
case .cancelled:
print("cancelled")
break
}
}
} catch {
print(error)
//return
}
}
})
}
func compressVideo(inputURL: URL, outputURL: URL, handler:@escaping (_ exportSession: AVAssetExportSession?)-> Void) {
let urlAsset = AVURLAsset(url: inputURL, options: nil)
guard let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality) else {
handler(nil)
return
}
exportSession.outputURL = outputURL
exportSession.outputFileType = AVFileType.mp4
exportSession.shouldOptimizeForNetworkUse = true
exportSession.exportAsynchronously { () -> Void in
handler(exportSession)
}
}
//use SDAVAssetExportSession library with dynamic bitrate
func aVodzLatestVideoCompressor(inputURL: URL, aOutputURL: URL, aStartTime:Float, aEndTime:Float) {
let sizeVideo:Float = inputURL.verboseFileSizeInMB()
if sizeVideo < 5.0 {
DispatchQueue.main.async {
//self.directsendvideowithoutcomressor()
}
return
}
let startTime = CMTime(seconds: Double(aStartTime), preferredTimescale: 1000)
let endTime = CMTime(seconds: Double(aEndTime), preferredTimescale: 1000)
let timeRange = CMTimeRange(start: startTime, end: endTime)
let anAsset = AVURLAsset(url: inputURL, options: nil)
guard let videoTrack = anAsset.tracks(withMediaType: AVMediaType.video).first else { return }
var aQuality:Float = 0.0
var duration = anAsset.duration
let totalSeconds = Int(CMTimeGetSeconds(duration))
print("duration -\(duration) - totalSeconds -\(totalSeconds)")
var bitrate = min(aQuality, videoTrack.estimatedDataRate)
let landscap = self.isLandScapVideo(afileURL: inputURL )
var originalWidth = videoTrack.naturalSize.width
var originalHeight = videoTrack.naturalSize.height
print("originalWidth -\(originalWidth) originalHeight- \(originalHeight) ")
while (originalWidth >= 1920 || originalHeight >= 1920) {
originalWidth = originalWidth / 2
originalHeight = originalHeight / 2
}
var setWidth = Int(originalWidth)
var setlHeight = Int(originalHeight)
if sizeVideo < 10.0 {
// COMPRESS_QUALITY_HIGH:
setWidth = Int(originalWidth)
setlHeight = Int(originalHeight)
aQuality = Float(setWidth * setlHeight * 20)
bitrate = min(aQuality, videoTrack.estimatedDataRate)
}else if sizeVideo < 20.0 {
//COMPRESS_QUALITY_MEDIUM:
if totalSeconds > 35{
setWidth = Int(originalWidth / 2.7)
setlHeight = Int(originalHeight / 2.7)
}else if totalSeconds > 25 {
setWidth = Int(originalWidth / 2.3)
setlHeight = Int(originalHeight / 2.3)
}else{
setWidth = Int(originalWidth / 2.0)
setlHeight = Int(originalHeight / 2.0)
}
aQuality = Float(setWidth * setlHeight * 10)
bitrate = min(aQuality, videoTrack.estimatedDataRate)
}else if sizeVideo < 30.0 {
//COMPRESS_QUALITY_MEDIUM:
if totalSeconds > 35{
setWidth = Int(originalWidth / 3)
setlHeight = Int(originalHeight / 3)
}else if totalSeconds > 20 {
setWidth = Int(originalWidth / 2.5)
setlHeight = Int(originalHeight / 2.5)
}else{
setWidth = Int(originalWidth / 2.0)
setlHeight = Int(originalHeight / 2.0)
}
aQuality = Float(setWidth * setlHeight * 10)
bitrate = min(aQuality, videoTrack.estimatedDataRate)
}else{
if totalSeconds > 35{
setWidth = Int(originalWidth / 3.0)
setlHeight = Int(originalHeight / 3.0)
}else if totalSeconds > 25 {
setWidth = Int(originalWidth / 2.5)
setlHeight = Int(originalHeight / 2.5)
}else{
setWidth = Int(originalWidth / 2.0)
setlHeight = Int(originalHeight / 2.0)
}
aQuality = Float(setWidth * setlHeight * 10)
bitrate = min(aQuality, videoTrack.estimatedDataRate)
}
print("aQuality")
print(Float(aQuality))
print("bitrate")
print(Float(bitrate))
let encoder = SDAVAssetExportSession(asset: anAsset)
encoder?.shouldOptimizeForNetworkUse = true
encoder?.timeRange = timeRange
encoder?.outputFileType = AVFileType.mp4.rawValue
encoder?.outputURL = aOutputURL
//960 X 540 , 1280 * 720 , 1920*1080 // size reduce parameter
encoder?.videoSettings = [
AVVideoCodecKey: AVVideoCodecType.h264,
AVVideoWidthKey: landscap ? NSNumber(value:1280) : NSNumber(value:720) ,
AVVideoHeightKey: landscap ? NSNumber(value:720) : NSNumber(value:1280),
AVVideoCompressionPropertiesKey: [
AVVideoAverageBitRateKey: NSNumber(value: bitrate),
AVVideoProfileLevelKey: AVVideoProfileLevelH264High40
]
]
encoder?.audioSettings = [
AVFormatIDKey: NSNumber(value: kAudioFormatMPEG4AAC),
AVNumberOfChannelsKey: NSNumber(value: 2),
AVSampleRateKey: NSNumber(value: 44100),
AVEncoderBitRateKey: NSNumber(value: 128000)
]
encoder?.exportAsynchronously(completionHandler: {
if encoder?.status == .completed {
print("Video export succeeded")
DispatchQueue.main.async {
appDelegate.hideLoader()
//NotificationCenter.default.post(name: Notification.Name("getMediaEffect"), object: "3")
//self.sendCompletion?(UIImage(), aOutputURL)
let text = "Original video- \(inputURL.verboseFileSizeInMB()) \n and Compressed video \(aOutputURL.verboseFileSizeInMB()) "
let alertController = UIAlertController.init(title: "Compressed!!", message: text , preferredStyle: .alert)
alertController.addAction(UIAlertAction.init(title: "share to server!", style: .default, handler: { (action) in
// Completion block
NotificationCenter.default.post(name: Notification.Name("getMediaEffect"), object: "3")
self.sendCompletion?(UIImage(), aOutputURL)
}))
alertController.addAction(UIAlertAction.init(title: "Save", style: .default, handler: { (action) in
// Completion block
DispatchQueue.main.async {
appDelegate.hideLoader()
if let videoURL = aOutputURL as? URL{
self.shareVideo(aUrl:videoURL )
}
}
}))
alertController.addAction(UIAlertAction.init(title: "cancel!", style: .default, handler: { (action) in
}))
self.present(alertController, animated: true, completion: nil)
}
} else if encoder?.status == .cancelled {
print("Video export cancelled")
DispatchQueue.main.async {
appDelegate.hideLoader()
self.view.makeToast("error_something_went_wrong".localized)
}
} else {
print("Video export failed with error: \(encoder!.error.localizedDescription) ")
DispatchQueue.main.async {
appDelegate.hideLoader()
self.view.makeToast("error_something_went_wrong".localized)
}
}
})
}
func isLandScapVideo(afileURL: URL) -> Bool{
let resolution = self.resolutionForLocalVideo(url: afileURL)
guard let width = resolution?.width, let height = resolution?.height else {
return false
}
if abs(width) > abs(height){
//landscap
return true
}else{
//potrait
return false
}
}
extension URL {
func verboseFileSizeInMB() -> Float{
let p = self.path
let attr = try? FileManager.default.attributesOfItem(atPath: p)
if let attr = attr {
let fileSize = Float(attr[FileAttributeKey.size] as! UInt64) / (1024.0 * 1024.0)
print(String(format: "FILE SIZE: %.2f MB", fileSize))
return fileSize
} else {
return Float.zero
}
}
}
//Extra At SDAVAssetExportSession library changes below at m file:(changes as per your requirement)
—— CGAffineTransform matrix = CGAffineTransformMakeTranslation(transx / xratio, transy / yratio - transform.ty);
——//fix Orientation - 1
UIImageOrientation videoAssetOrientation = UIImageOrientationUp;
BOOL isVideoAssetPortrait = NO;
CGAffineTransform videoTransform = videoTrack.preferredTransform;
if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
videoAssetOrientation = UIImageOrientationRight;
isVideoAssetPortrait = YES;
}
if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {
videoAssetOrientation = UIImageOrientationLeft;
isVideoAssetPortrait = YES;
}
if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
videoAssetOrientation = UIImageOrientationUp;
}
if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
videoAssetOrientation = UIImageOrientationDown;
}
// [passThroughLayer setTransform:transform atTime:kCMTimeZero];
if ((videoAssetOrientation = UIImageOrientationDown) || (videoAssetOrientation = UIImageOrientationLeft)){
[passThroughLayer setTransform:videoTrack.preferredTransform atTime:kCMTimeZero];
}else{
[passThroughLayer setTransform:transform atTime:kCMTimeZero];
}