![](/img/trans.png)
[英]UIImagePickerController allowsEditing = YES not working
[英]UIImagePickerController allowsEditing = YES, getting untrimmed video after trimming
問題:
當我在我的UIImagePickerController
錄制視頻時,allowEditing設置為YES,然后使用視頻捕獲后的trim-interface修剪視頻,我返回原始視頻,而不是修剪過的視頻。
建立:
我使用UIImagePickerController
進行視頻捕獲,將allowsEditing
屬性設置為YES。 在委托方法didFinishPickingMediaWithInfo
,我使用來自info NSDictionary
UIImagePickerControllerMediaURL
來獲取路徑URL。 官方的Apple文檔遺憾的是沒有提到任何已編輯的視頻網址。
碼:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
if (CFStringCompare ((__bridge CFStringRef) mediaType, kUTTypeMovie, 0)
== kCFCompareEqualTo) {
self.tempVideoPath = [[info objectForKey:
UIImagePickerControllerMediaURL] path];
}
}
我意識到這個問題類似於其他 的人在這里張貼在SO,但沒有明確的答案,為什么它不工作或者為什么選擇是即使在那里。 如果它是這樣的,我不明白為什么選擇器有'allowsEditing'屬性。
編輯:在我收到的信息詞典中有以下鍵:
info: {
UIImagePickerControllerMediaType = "public.movie";
UIImagePickerControllerMediaURL = "file://localhost/private/var/mobile/Applications/F12E4608-FE5A-4EE3-B4E2-8F7D2508C4C8/tmp/capture-T0x21d810.tmp.wabFCC/capturedvideo.MOV";
"_UIImagePickerControllerVideoEditingEnd" = "5.498333333333333";
"_UIImagePickerControllerVideoEditingStart" = "4.273402690887451";
}
這是否意味着我們必須自己修剪這些數據? 那么Apple文檔對此並不十分清楚。 如果是這樣,你知道一個好的做法嗎?
您需要使用UIVideoEditorController
進行此操作。 它的委托協議指定了一個方法videoEditorController:didSaveEditedVideoToPath:
這似乎是你想要的。 這里提供了示例代碼,如本SO問題所述 。
這是一個快速而又臟的Swift 5示例,介紹如何從UIImagePickerController
修剪視頻
extension ViewController: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let mediaType = info[.mediaType] as! String
dismiss(animated: true) { [weak self] in
// Handle a movie capture
if mediaType == kUTTypeMovie as String {
guard let videoURL = info[.mediaURL] as? URL else {
SwiftyBeaver.error("Could not get URL for movie")
return
}
let editingEnd = UIImagePickerController.InfoKey(rawValue: "_UIImagePickerControllerVideoEditingEnd")
let editingStart = UIImagePickerController.InfoKey(rawValue: "_UIImagePickerControllerVideoEditingStart")
let startMilliseconds: Double?
let endMilliseconds: Double?
if let start = info[editingStart] as? Double, let end = info[editingEnd] as? Double {
startMilliseconds = start
endMilliseconds = end
} else {
startMilliseconds = nil
endMilliseconds = nil
}
let alert = UIAlertController(title: "Creating", message: "File is being processed", preferredStyle: .alert)
self?.present(alert, animated: true)
self?.process(srcVideoURL: videoURL, startSeconds: startMilliseconds, endSeconds: endMilliseconds) { (error) in
DispatchQueue.main.async {
if let error = error {
alert.title = "Whoops"
alert.message = "\(error)"
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
self?.dismiss(animated: true, completion: nil)
}))
return
}
self?.dismiss(animated: true, completion: nil)
}
}
}
}
}
}
enum VideoError: Error {
case error(message: String)
}
extension ViewController {
func process(srcVideoURL: URL, startSeconds: Double?, endSeconds: Double?, completed: @escaping (_ error: Error?) -> ()) {
DispatchQueue.global(qos: .userInitiated).async {
let dstVideoURL: URL // some URL for the destination
do {
try self.handleNewVideo(srcVideoURL: srcVideoURL, dstVideoURL: dstVideoURL, startSeconds: startSeconds, endSeconds: endSeconds)
completed(nil)
} catch {
completed(error)
}
}
}
func handleNewVideo(srcVideoURL: URL, dstVideoURL: URL, startSeconds: Double?, endSeconds: Double?) throws {
guard let start = startSeconds, let end = endSeconds else {
print("No video editing information. Copying file.")
try FileManager.default.moveItem(at: srcVideoURL, to: dstVideoURL)
return
}
print("Video editing information. Processing start \(start) end \(end).")
let videoAsset = AVURLAsset(url: srcVideoURL)
let exportSession = AVAssetExportSession(asset: videoAsset, presetName: AVAssetExportPresetHighestQuality)!
exportSession.outputURL = dstVideoURL
exportSession.outputFileType = AVFileType.mov
let timeRange = CMTimeRange(start: CMTime(seconds: start, preferredTimescale: 1000), duration: CMTime(seconds: end - start, preferredTimescale: 1000))
exportSession.timeRange = timeRange
var error: Error? = nil
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
exportSession.exportAsynchronously(completionHandler: {
switch exportSession.status {
case .completed:
break
case .failed:
error = exportSession.error ?? VideoError.error(message: "Unknown failed error")
case .cancelled:
error = exportSession.error ?? VideoError.error(message: "Video Cancelled")
case .exporting:
error = exportSession.error ?? VideoError.error(message: "Video still exporting")
case .unknown:
error = exportSession.error ?? VideoError.error(message: "Unknown unknown error")
case .waiting:
error = exportSession.error ?? VideoError.error(message: "Waiting error")
@unknown default:
error = exportSession.error ?? VideoError.error(message: "Future error")
}
dispatchGroup.leave()
})
dispatchGroup.wait()
if let error = error {
throw error
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.