Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何使用AVFoundation修剪视频_Iphone_Video - Fatal编程技术网

Iphone 如何使用AVFoundation修剪视频

Iphone 如何使用AVFoundation修剪视频,iphone,video,Iphone,Video,我可以使用AVFoundation或UIImagePickerController录制视频。但我无法将视频从一秒剪辑到另一秒。有人能帮我吗 谢谢, 湿婆奎师那。您可以让UIImagePickerController启用修剪 UIImagePickerController *videoRecorder = [[UIImagePickerController alloc]init]; NSArray *sourceTypes = [UIImagePickerCont

我可以使用AVFoundation或UIImagePickerController录制视频。但我无法将视频从一秒剪辑到另一秒。有人能帮我吗

谢谢,
湿婆奎师那。

您可以让UIImagePickerController启用修剪

UIImagePickerController *videoRecorder = [[UIImagePickerController alloc]init];         
        NSArray *sourceTypes = [UIImagePickerController availableMediaTypesForSourceType:videoRecorder.sourceType];
        NSLog(@"Available types for source as camera = %@", sourceTypes);
        if (![sourceTypes containsObject:(NSString*)kUTTypeMovie] ) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil 
                                                            message:@"Device Not Supported for video Recording."                                                                       delegate:self 
                                                  cancelButtonTitle:@"Yes" 
                                                  otherButtonTitles:@"No",nil];
            [alert show];
            [alert release];
            return;
        }
        videoRecorder.allowsEditing = YES;
不幸的是,从imagePickerController返回后,您不得不手动转换视频

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
{
    if ([self.popoverLibraryBrowser isPopoverVisible])
    {
        [self.popoverLibraryBrowser dismissPopoverAnimated:YES];
    }
    NSString *type = [info objectForKey:UIImagePickerControllerMediaType];
    if ([type isEqualToString:(NSString *)kUTTypeVideo] || 
        [type isEqualToString:(NSString *)kUTTypeMovie]) { // movie != video
        NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];


        NSNumber *start = [info objectForKey:@"_UIImagePickerControllerVideoEditingStart"];
        NSNumber *end = [info objectForKey:@"_UIImagePickerControllerVideoEditingEnd"];

        // if start and end are nil then clipping was not used.
        // You should use the entire video.


        int startMilliseconds = ([start doubleValue] * 1000);
        int endMilliseconds = ([end doubleValue] * 1000);

        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];

        NSFileManager *manager = [NSFileManager defaultManager];

        NSString *outputURL = [documentsDirectory stringByAppendingPathComponent:@"output"] ;
        [manager createDirectoryAtPath:outputURL withIntermediateDirectories:YES attributes:nil error:nil];

        outputURL = [outputURL stringByAppendingPathComponent:@"output.mp4"];
        // Remove Existing File
        [manager removeItemAtPath:outputURL error:nil];


        //[self loadAssetFromFile:videoURL];

        [self.recorder dismissModalViewControllerAnimated:YES];

        AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil]; 


        AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:videoAsset presetName:AVAssetExportPresetHighestQuality];
        exportSession.outputURL = [NSURL fileURLWithPath:outputURL];
        exportSession.outputFileType = AVFileTypeQuickTimeMovie;
        CMTimeRange timeRange = CMTimeRangeMake(CMTimeMake(startMilliseconds, 1000), CMTimeMake(endMilliseconds - startMilliseconds, 1000));
        exportSession.timeRange = timeRange;

        [exportSession exportAsynchronouslyWithCompletionHandler:^{
            switch (exportSession.status) {
                case AVAssetExportSessionStatusCompleted:
                    // Custom method to import the Exported Video
                    [self loadAssetFromFile:exportSession.outputURL];
                    break;
                case AVAssetExportSessionStatusFailed:
                    //
                    NSLog(@"Failed:%@",exportSession.error);
                    break;
                case AVAssetExportSessionStatusCancelled:
                    //
                    NSLog(@"Canceled:%@",exportSession.error);
                    break;
                default:
                    break;
            }
        }];



        //NSData *videoData = [NSData dataWithContentsOfURL:videoURL];
        //NSString *videoStoragePath;//Set your video storage path to this variable
        //[videoData writeToFile:videoStoragePath atomically:YES];
        //You can store the path of the saved video file in sqlite/coredata here.
    }
}

您应该在setMediaTypes数组中添加kUTTypeMovie,它将起作用。

以上的Swift版本

import UIKit
import AVFoundation
import MobileCoreServices

func pickVideo(){
    if UIImagePickerController.isSourceTypeAvailable(.Camera) {
        let videoRecorder = UIImagePickerController()
        videoRecorder.sourceType = .Camera
        videoRecorder.mediaTypes = [kUTTypeMovie as String]
        videoRecorder.allowsEditing = true
        videoRecorder.delegate = self

        presentViewController(videoRecorder, animated: true, completion: nil)
    }
}


func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
    picker.dismissViewControllerAnimated(true, completion: nil)
    let manager = NSFileManager.defaultManager()

    guard let documentDirectory = try? manager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true) else {return}
    guard let mediaType = info[UIImagePickerControllerMediaType] as? String else {return}
    guard let url = info[UIImagePickerControllerMediaURL] as? NSURL else {return}

    if mediaType == kUTTypeMovie as String || mediaType == kUTTypeVideo as String {
        let asset = AVAsset(URL: url)
        let length = Float(asset.duration.value) / Float(asset.duration.timescale)
        print("video length: \(length) seconds")

        let start = info["_UIImagePickerControllerVideoEditingStart"] as? Float
        let end = info["_UIImagePickerControllerVideoEditingEnd"] as? Float


        var outputURL = documentDirectory.URLByAppendingPathComponent("output")


        do {
            try manager.createDirectoryAtURL(outputURL, withIntermediateDirectories: true, attributes: nil)
            outputURL = outputURL.URLByAppendingPathComponent("output.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)")

            case .Failed:
                print("failed \(exportSession.error)")

            case .Cancelled:
                print("cancelled \(exportSession.error)")

            default: break
            }
        }
    }
}

我找到了swift 4的最佳解决方案。我确实根据自己的需要修复了它,但它非常清晰和方便

守则:

import-AVFoundation
进口基金会
扩展文件管理器{
func removefileifneeded(在url:url处)引发{
保护文件存在(atPath:url.path)或其他{
返回
}
做{
尝试删除项目(位于:url)
}
捕捉错误{
抛出TrimError(“无法删除现有目标文件:\(错误)”)
}
}
}
结构TrimError:错误{
let description:字符串
让我们看看错误:错误?
初始化(uu说明:字符串,underyingError:错误?=nil){
self.description=“TrimVideo:+说明
self.underyingerror=underyingerror
}
}
扩展可变合成{
便利初始化(资产:AVAsset){
self.init()
对于asset.tracks中的track{
addMutableTrack(withMediaType:track.mediaType,preferredTrackID:track.trackID)
}
}
func微调(timeOffStart:Double){
let duration=CMTime(秒:timeOffStart,首选时间刻度:1)
let timeRange=CMTimeRange(开始:kCMTimeZero,持续时间:持续时间)
轨道中的轨道{
track.removeTimeRange(时间范围)
}
removeTimeRange(时间范围)
}
}
扩展AVAsset{
func assetByTrimming(timeOffStart:Double)抛出->AVAsset{
let duration=CMTime(秒:timeOffStart,首选时间刻度:1)
let timeRange=CMTimeRange(开始:kCMTimeZero,持续时间:持续时间)
let composition=AVMutableComposition()
做{
轨道中的轨道{
让compositionTrack=composition.addMutableTrack(withMediaType:track.mediaType,preferredTrackID:track.trackID)
尝试compositionTrack?.insertTimeRange(时间范围,of:track,at:kCMTimeZero)
}
}捕捉错误{
抛出TrimError(“合成过程中的错误”,参考错误:错误)
}
返回组合
}
func导出(到目标:URL)抛出{
guard let exportSession=AVAssetExportSession(资产:self,预设名称:AVAssetExportPresetPassthrough)else{
抛出错误(“无法创建导出会话”)
}
exportSession.outputURL=目的地
exportSession.outputFileType=AVFileType.m4v
exportSession.shouldOptimizationForNetworkUse=true
let group=DispatchGroup()
group.enter()
请尝试FileManager.default.RemoveFileIf必要时(在:目标)
exportSession.exportAsynchronously{
小组请假()
}
组。等待()
如果let error=exportSession.error{
抛出TrimError(“导出期间出错”,参考错误:错误)
}
}
}
函数时间(u操作:()抛出->())重试{
让我们开始=日期()
尝试操作()
让end=Date().timeIntervalSince(开始)
列印(完)
让sourceURL=URL(fileURLWithPath:CommandLine.arguments[1])
让destinationURL=URL(fileURLWithPath:CommandLine.arguments[2])
做{
试一试{
let asset=avurlaste(url:sourceURL)
让trimmedAsset=try asset.assetByTrimming(timeOffStart:1.0)
尝试trimmedAsset.export(到:destinationURL)
}
}捕捉错误{

print(“在查找用于修剪现有视频的内容时发现此问题。修剪捕获的视频相对简单。但是,让修剪窗口显示出来似乎让我难以理解。我希望下面的答案能有所帮助。感谢您提供的源代码。当我使用“*sourceTypes”作为“UIImagePickerController源类型摄影机”时,我得到了”*开始和结束时间。但当我使用“*sourceTypes”作为“UIImagePickerControllerSourceTypeSavedPhotosAlbum”时,我没有获得“开始和结束”时间。问题是什么?我如何获得“开始和结束”时间?你给了他们“剪辑”的能力吗"视频?填充编辑开始和结束的部分是剪辑。如果不剪辑视频,则这些值保留为零,这意味着应跳过剪辑并使用整个视频。请参阅此处的日志。我允许用户从缩略图中选择帧。如果我编辑,则没有问题“摄像机录制的视频”和问题发生在我尝试从相册中加载的视频中选择帧时。@karthi使用
UIImagePickerControllerSourceTypeSavedPhotosAlbum
时,您从
[info objectForKey:UIImagePickerControllerDiaUrl]获得的url;
引用了一个修剪过的视频文件,因此不需要开始和结束时间。我知道这一点,因为我从
[info objectForKey:uiimagepickercontrollermediaaurl]获取url的持续时间;
并将其与原始视频持续时间进行比较。不应检查电影或视频,而应检查类型是否符合电影:
uttypeconformisto((uu-bridge CFStringRef)mediaType,kuttypeMoine)!=0
。电影和视频也是如此。对于某些视频,此解决方案失败。有什么建议吗?作为程序员,您应该知道“失败”这不是描述错误/问题的合适方式。云视频失败了,我调试并解决了。我告诉失败了,因为我无法得到一个场景,所以想问你,如果你遇到任何像这样奇怪的问题。无论如何,我已经解决了这个问题。下次请和任何人好好谈谈