场景:
我希望减少iTouch照片库中单个视频的大小。
1.从库中收集视频资产。
2.获取PHAsset的缩略图 - 有效。
3.从库中获取实际视频。
4.从库中请求AVAssetForVideo。
5.通过ExportSessions转换视频...加载各种参数。
6.尝试将导出运行到tmp目录以供使用。
* FAILS *
这是调试输出:
这是错误信息:
func getVideoFromPhotoLibrary() {
let videoAssets = PHAsset.fetchAssetsWithMediaType(.Video, options:nil)
videoAssets.enumerateObjectsUsingBlock {
(obj:AnyObject!, index:Int, stop:UnsafeMutablePointer<ObjCBool>) in
let mySize = CGSizeMake(120,120)
let myAsset = obj as! PHAsset
let imageManager = PHImageManager.defaultManager()
var myVideo:BlissMedium?
// Request the poster frame or the image of the video
imageManager.requestImageForAsset(myAsset, targetSize:mySize, contentMode: .AspectFit, options: nil) {
(imageResult, info) in
let thumbnail = UIImage(named:"videoRed")
myVideo = BlissMedium(blissImage: imageResult, creationDate:myAsset.creationDate)
myVideo!.mediumType = .video
}
// Actual Video:
imageManager.requestAVAssetForVideo(myAsset, options: nil, resultHandler: {result, audio, info in
let asset = result as! AVURLAsset
let mediaURL = asset.URL
let session = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetMediumQuality)
let filename = "composition.mp4"
session.outputURL = NSURL(string: NSTemporaryDirectory());
session.outputFileType = AVFileTypeQuickTimeMovie;
session.exportAsynchronouslyWithCompletionHandler({ () -> Void in
dispatch_async(dispatch_get_main_queue(), {
if session.status == AVAssetExportSessionStatus.Completed {
println("Success")
}
else {
println(session.error?.localizedDescription)
//The requested URL was not found on this server.
}
})
})
})
if nil != myVideo {
self.gBlissVideoMedia.append(myVideo!)
}
}
}
我检查确保目标路径/文件存在;然后我添加了'AVFileTypeMPEG4'输出类型以匹配预期的.mp4:
let targetDir = createTempDirectory("bliss/composition.mp4") as String?
if NSFileManager.defaultManager().fileExistsAtPath(targetDir!) {
println("*** file exists! ***")
} else {
return
}
session.outputURL = NSURL(string: targetDir!);
session.outputFileType = AVFileTypeMPEG4
我还有问题:
*文件存在! *
可选(“操作无法完成”)
我做错了什么;缺少什么?
<小时/> 更新:
但是......用Swift编写的相同代码失败了。
我注意到Swift中目标输出的绝对路径发生了变化,而在Objective-C中找不到:
也许这是一个Swift 1.2 bug ???
答案 0 :(得分:0)
我不确定你是否可以保存在temp目录的根目录中,我通常使用这个函数创建一个我可以使用的新临时目录:
func createTempDirectory(myDir: String) -> String? {
let tempDirectoryTemplate = NSTemporaryDirectory().stringByAppendingPathComponent(myDir)
let fileManager = NSFileManager.defaultManager()
var err: NSErrorPointer = nil
if fileManager.createDirectoryAtPath(tempDirectoryTemplate, withIntermediateDirectories: true, attributes: nil, error: err) {
return tempDirectoryTemplate
} else {
return nil
}
}
尝试在此函数返回的目录中进行转换。
我希望能帮到你!
答案 1 :(得分:0)
我不太明白代码的最后一部分是做什么的,你在哪里找出文件是否存在。您找到的是哪个文件?
由于我不明白,这可能无关紧要,但在您最顶层的代码中,我注意到您将filename
设置为composition.mp4
,但让outputURL
为{{ 1}}。由于我缺乏Swiftness,我可能会遗漏一些东西,但在我看来,好像你根本没有使用文件名,并试图将文件写为一个文件夹。我相信设置一个合适的URL可能会解决问题,但我不确定。一个Objective-c例子可能是:
NSURL(string: NSTemporaryDirectory())
outputURL应该指向实际文件,而不是它所在的文件夹。我想...
无论如何,如果这不起作用我也会有一些其他的想法。 你在实际的设备上试过吗?模拟器可能存在问题。
另外,遗憾的是,我已经无数次地遇到了错误NSURL * outputURL = [[NSURL alloc]
initFileURLWithPath:[NSString pathWithComponents:
@[NSTemporaryDirectory(), @"composition.mp4"]]];
不同的根问题,所以这并没有多大帮助。
而且,我看到你检查-12780
,你检查了实际状态是什么吗?是if session.status == AVAssetExportSessionStatus.Completed
还是.Failed
?有几种状态。
这可能是一个很长的镜头,但在我的一个应用程序中,我使用相机捕获视频/音频,然后使用.Unknown
对其进行编码/转换。开始录制时以及录制(导出)后都会出现奇怪的错误。我发现我可以更改AVAssetExportSession
,这显然与设备如何处理媒体有关。
我不知道如何使用Swift,但这是我的代码(在相关视图的viewDidAppear中)
AVAudioSession
类别NSError *error;
AVAudioSession *aSession = [AVAudioSession sharedInstance];
[aSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
[aSession setMode:AVAudioSessionModeVideoRecording error:&error];
[aSession setActive: YES error: &error];
让我能够更快地启动相机,并且可以摆脱偶尔的悬挂PlayAndRecord
和偶尔的坠机AVAssetExportSessionStatus.Unknown
(它也会使{{1} }} - 误差)