ユーザーが入力または選択した特定の開始点から特定の終了点まで、録画したビデオをトリミングする必要があるタスクに取り組んでいます。どうすればいいの?以前はUIVideoEditorController
を使用していましたが、デフォルトのビューを使用したくないので、ビデオを直接トリミングしたいと思います。
let FinalUrlTosave = NSURL(string: "\(newURL)")
exportSession!.outputURL=FinalUrlTosave
exportSession!.shouldOptimizeForNetworkUse = true
// exportSession.outputFileType = AVFileTypeQuickTimeMovie
exportSession!.outputFileType = AVFileTypeQuickTimeMovie;
let start:CMTime
let duration:CMTime
var st = starttime.doubleValue
var ed = endTime.doubleValue
start = CMTimeMakeWithSeconds(st, 600)
duration = CMTimeMakeWithSeconds(ed, 600)
// let timeRangeForCurrentSlice = CMTimeRangeMake(start, duration)
let range = CMTimeRangeMake(start, duration);
exportSession!.timeRange = range
exportSession!.exportAsynchronouslyWithCompletionHandler({
switch exportSession!.status{
case AVAssetExportSessionStatus.Failed:
print("failed \(exportSession!.error)")
case AVAssetExportSessionStatus.Cancelled:
print("cancelled \(exportSession!.error)")
default:
print("complete....complete")
// self.SaveVideoToPhotoLibrary(destinationURL1!)
}
})
これを使って目標を達成しようとしていますが、成功していません。
エラーメッセージ:
失敗オプション(エラードメイン= NSURLErrorDomainコード= -1100 "要求されたURLはこのサーバーで見つかりませんでした。" UserInfo = {NSErrorFailingURLStringKey = file:/// var/mobile/Containers/Data/Application/E68D3BFD-6923-4EA6-9FB3 -C020CE4AA9D4/Documents/moment/jGq_9AUFa47s2ZiiPP4x.mp4、NSErrorFailingURLKey = file:/// var/mobile/Containers/Data/Application/E68D3BFD-6923-4EA6-9FB3-C020CE4AA9D4/Documents/moment/jGq_9AUFこのサーバーでURLが見つかりませんでした。、NSUnderlyingError = 0x1553c220 {エラードメイン= N
2回目にエラーが発生しました:
失敗オプション(エラードメイン= NSURLErrorDomainコード= -3000 "ファイルを作成できません" UserInfo = {NSUnderlyingError = 0x14e00000 {エラードメイン= NSOSStatusErrorDomainコード= -12124 "(null)"}、NSLocalizedDescription =ファイルを作成できません})
私はこの方法を使用して私の解決策を見つけました、そしてそれは魅力のように働きます....
func cropVideo(sourceURL1: NSURL, statTime:Float, endTime:Float)
{
let manager = NSFileManager.defaultManager()
guard let documentDirectory = try? manager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true) else {return}
guard let mediaType = "mp4" as? String else {return}
guard let url = sourceURL1 as? NSURL else {return}
if mediaType == kUTTypeMovie as String || mediaType == "mp4" as String {
let asset = AVAsset(URL: url)
let length = Float(asset.duration.value) / Float(asset.duration.timescale)
print("video length: \(length) seconds")
let start = statTime
let end = endTime
var outputURL = documentDirectory.URLByAppendingPathComponent("output")
do {
try manager.createDirectoryAtURL(outputURL, withIntermediateDirectories: true, attributes: nil)
let name = Moment.newName()
outputURL = outputURL.URLByAppendingPathComponent("\(name).mp4")
}catch let error {
print(error)
}
//Remove existing file
_ = try? manager.removeItemAtURL(outputURL)
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else {return}
exportSession.outputURL = outputURL
exportSession.outputFileType = AVFileTypeMPEG4
let startTime = CMTime(seconds: Double(start ?? 0), preferredTimescale: 1000)
let endTime = CMTime(seconds: Double(end ?? length), preferredTimescale: 1000)
let timeRange = CMTimeRange(start: startTime, end: endTime)
exportSession.timeRange = timeRange
exportSession.exportAsynchronouslyWithCompletionHandler{
switch exportSession.status {
case .Completed:
print("exported at \(outputURL)")
self.saveVideoTimeline(outputURL)
case .Failed:
print("failed \(exportSession.error)")
case .Cancelled:
print("cancelled \(exportSession.error)")
default: break
}
}
}
}
このためのSwift4バージョン。
static func cropVideo(sourceURL: URL, startTime: Double, endTime: Double, completion: ((_ outputUrl: URL) -> Void)? = nil)
{
let fileManager = FileManager.default
let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let asset = AVAsset(url: sourceURL)
let length = Float(asset.duration.value) / Float(asset.duration.timescale)
print("video length: \(length) seconds")
var outputURL = documentDirectory.appendingPathComponent("output")
do {
try fileManager.createDirectory(at: outputURL, withIntermediateDirectories: true, attributes: nil)
outputURL = outputURL.appendingPathComponent("\(sourceURL.lastPathComponent).mp4")
}catch let error {
print(error)
}
//Remove existing file
try? fileManager.removeItem(at: outputURL)
guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) else { return }
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
let timeRange = CMTimeRange(start: CMTime(seconds: startTime, preferredTimescale: 1000),
end: CMTime(seconds: endTime, preferredTimescale: 1000))
exportSession.timeRange = timeRange
exportSession.exportAsynchronously {
switch exportSession.status {
case .completed:
print("exported at \(outputURL)")
completion?(outputURL)
case .failed:
print("failed \(exportSession.error.debugDescription)")
case .cancelled:
print("cancelled \(exportSession.error.debugDescription)")
default: break
}
}
}
func cropVideo1(_ sourceURL1: URL, statTime:Float, endTime:Float){
let videoAsset: AVAsset = AVAsset(url: sourceURL1) as AVAsset
let composition = AVMutableComposition()
composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = CGSize(width: 1280, height: 768)
videoComposition.frameDuration = CMTimeMake(8, 15)
let instruction = AVMutableVideoCompositionInstruction()
let length = Float(videoAsset.duration.value)
print(length)
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30))
let start = statTime
let end = endTime
let exportSession = AVAssetExportSession(asset: videoAsset, presetName: AVAssetExportPresetHighestQuality)!
exportSession.outputFileType = AVFileTypeMPEG4
let startTime = CMTime(seconds: Double(start ), preferredTimescale: 1000)
let endTime = CMTime(seconds: Double(end ), preferredTimescale: 1000)
let timeRange = CMTimeRange(start: startTime, end: endTime)
exportSession.timeRange = timeRange
let formatter = DateFormatter()
formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"
let date = Date()
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let outputPath = "\(documentsPath)/\(formatter.string(from: date)).mp4"
let outputURL = URL(fileURLWithPath: outputPath)
exportSession.outputURL = outputURL
exportSession.outputFileType = AVFileTypeQuickTimeMovie
print("sucess")
exportSession.exportAsynchronously(completionHandler: { () -> Void in
DispatchQueue.main.async(execute: {
self.exportDidFinish(exportSession)
print("sucess")
})
})
}
func exportDidFinish(_ session: AVAssetExportSession) {
if session.status == AVAssetExportSessionStatus.completed {
let outputURL = session.outputURL
let library = ALAssetsLibrary()
if library.videoAtPathIs(compatibleWithSavedPhotosAlbum: outputURL) {
library.writeVideoAtPath(toSavedPhotosAlbum: outputURL) { alAssetURL, error in
if error != nil {
DispatchQueue.main.async(execute: {
print("Failed to save video")
})
} else {
DispatchQueue.main.async(execute: {
Print("Sucessfully saved Video")
})
}
self.activityIndicator.stopAnimating()
}
}
}
}