扣扣空间说说浏览是怎么记录的 - qq名片赞0.1元十万赞,飞速低价快

自助下单地址(拼多多砍价,ks/qq/dy赞等业务):点我进入

本文检查以下函数:

录制视频需要真机测试!

效果图

视频录制

首先我们弹出系统的视频录制界面,由UIImagePickerController控制器实现,但是需要验证用户权限。 只有获得录制视频的权限,我们才能继续。

我们还需要判断 UIImagePickerControllerSourceTypeCamera 是否支持。 比如模拟器不支持。 当然真机不支持我们不知道,但是这样写还是比较稳妥的。 视频录制可以通过videoQuality属性设置录制视频的质量,即码率。 我们还可以通过videoMaximumDuration属性设置来设置录制视频的最大时长,比如这里设置为5分钟。

扣扣空间说说浏览是怎么记录的 - qq名片赞0.1元十万赞,飞速低价快

// 7.0
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (authStatus == AVAuthorizationStatusRestricted
    || authStatus == AVAuthorizationStatusDenied) {
  NSLog(@"摄像头已被禁用,您可在设置应用程序中进行开启");
  return;
}
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
  UIImagePickerController *picker = [[UIImagePickerController alloc] init];
  picker.delegate = self;
  picker.allowsEditing = YES;
  picker.sourceType = UIImagePickerControllerSourceTypeCamera;
  picker.videoQuality = UIImagePickerControllerQualityType640x480; //录像质量
  picker.videoMaximumDuration = 5 * 60.0f; // 限制视频录制最多不超过5分钟
  picker.mediaTypes = @[(NSString *)kUTTypeMovie];
  [self presentViewController:picker animated:YES completion:NULL];
  self.shouldAsync = YES;
} else {
  NSLog(@"手机不支持摄像");
}

然后实现代理,就可以拿到录制的视频了。

从相机胶卷中选择视频

从相册中选择视频与弹出录制视频的代码类似,只是sourceType不同。 我们还要求先判断权限,用户是否被授权,如果没有,就没办法了。

指定 sourceType 为 UIImagePickerControllerSourceTypeSavedPhotosAlbum 是为了获取相册中保存的媒体。 我们还需要指定mediaTypes,设置为kUTTypeMovie即可。

AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (authStatus == AVAuthorizationStatusRestricted
    || authStatus == AVAuthorizationStatusDenied) {
  NSLog(@"摄像头已被禁用,您可在设置应用程序中进行开启");
  return;
}
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
  UIImagePickerController *picker = [[UIImagePickerController alloc] init];
  picker.delegate = self;
  picker.allowsEditing = YES;
  picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
  picker.mediaTypes = @[(NSString *)kUTTypeMovie];
  [self presentViewController:picker animated:YES completion:NULL];
  self.shouldAsync = NO;
} else {
  NSLog(@"手机不支持摄像");
}

扣扣空间说说浏览是怎么记录的 - qq名片赞0.1元十万赞,飞速低价快

同理,通过实现代理方法,即可获取到选中的视频。

将视频保存到相机胶卷

写入相册可以通过ALAssetsLibrary类来实现,该类提供了写入相册的API,异步写入,完成是返回主线程更新UI:

NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
  // 判断相册是否兼容视频,兼容才能保存到相册
  if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:videoURL]) {
    [library writeVideoAtPathToSavedPhotosAlbum:videoURL completionBlock:^(NSURL *assetURL, NSError *error) {
      dispatch_async(dispatch_get_main_queue(), ^{
        // 写入相册
        if (error == nil) {
            NSLog(@"写入相册成功");
        } else {
           NSLog(@"写入相册失败");
        }
      }
    }];
  }
});

获取视频帧图像 同步获取帧图像

要同步获取中间帧,需要指定那个时间点的帧。 获取后返回的图像对象是CFRetained,需要在外面自动CGImageRelease释放显存。 通过AVAsset访问特定的视频资源,然后通过AVAssetImageGenerator图像生成器生成一帧图像:

扣扣空间说说浏览是怎么记录的 - qq名片赞0.1元十万赞,飞速低价快

// Get the video's center frame as video poster image
- (UIImage *)frameImageFromVideoURL:(NSURL *)videoURL {
  // result
  UIImage *image = nil;
  // AVAssetImageGenerator
  AVAsset *asset = [AVAsset assetWithURL:videoURL];
  AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
  imageGenerator.appliesPreferredTrackTransform = YES;
  // calculate the midpoint time of video
  Float64 duration = CMTimeGetSeconds([asset duration]);
  // 取某个帧的时间,参数一表示哪个时间(秒),参数二表示每秒多少帧
  // 通常来说,600是一个常用的公共参数,苹果有说明:
  // 24 frames per second (fps) for film, 30 fps for NTSC (used for TV in North America and
  // Japan), and 25 fps for PAL (used for TV in Europe).
  // Using a timescale of 600, you can exactly represent any number of frames in these systems
  CMTime midpoint = CMTimeMakeWithSeconds(duration / 2.0, 600);
  // get the image from
  NSError *error = nil;
  CMTime actualTime;
  // Returns a CFRetained CGImageRef for an asset at or near the specified time.
  // So we should mannully release it
  CGImageRef centerFrameImage = [imageGenerator copyCGImageAtTime:midpoint
                                                       actualTime:&actualTime
                                                            error:&error];
  if (centerFrameImage != NULL) {
    image = [[UIImage alloc] initWithCGImage:centerFrameImage];
    // Release the CFRetained image
    CGImageRelease(centerFrameImage);
  }
  return image;
}

异步获取帧图像

异步获取某一帧的图片,与同步相比,只是调用API不同,可以传递多个时间点,然后估计实际时间返回图片,但是返回的图片不需要我们自动释放再次。 有可能获取不到图片,所以需要判断是否是AVAssetImageGeneratorSucceeded,然后进行图片转换:

// 异步获取帧图片,可以一次获取多帧图片
- (void)centerFrameImageWithVideoURL:(NSURL *)videoURL completion:(void (^)(UIImage *image))completion {
  // AVAssetImageGenerator
  AVAsset *asset = [AVAsset assetWithURL:videoURL];
  AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
  imageGenerator.appliesPreferredTrackTransform = YES;
  // calculate the midpoint time of video
  Float64 duration = CMTimeGetSeconds([asset duration]);
  // 取某个帧的时间,参数一表示哪个时间(秒),参数二表示每秒多少帧
  // 通常来说,600是一个常用的公共参数,苹果有说明:
  // 24 frames per second (fps) for film, 30 fps for NTSC (used for TV in North America and
  // Japan), and 25 fps for PAL (used for TV in Europe).
  // Using a timescale of 600, you can exactly represent any number of frames in these systems
  CMTime midpoint = CMTimeMakeWithSeconds(duration / 2.0, 600);
  // 异步获取多帧图片
  NSValue *midTime = [NSValue valueWithCMTime:midpoint];
  [imageGenerator generateCGImagesAsynchronouslyForTimes:@[midTime] completionHandler:^(CMTime requestedTime, CGImageRef  _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) {
    if (result == AVAssetImageGeneratorSucceeded && image != NULL) {
      UIImage *centerFrameImage = [[UIImage alloc] initWithCGImage:image];
      dispatch_async(dispatch_get_main_queue(), ^{
        if (completion) {
          completion(centerFrameImage);
        }
      });
    } else {
      dispatch_async(dispatch_get_main_queue(), ^{
        if (completion) {
          completion(nil);
        }
      });
    }
  }];
}

压缩和导入视频

压缩视频是因为高视频码率生成的视频体积太大。 对于联通设备cf保存的录像怎么上传,内存不宜过大。 如果不支持分片上传到服务器,或者不支持流上传或者文件上传,但是只能支持表单上传,那么一定要限制大小,压缩视频。

扣扣空间说说浏览是怎么记录的 - qq名片赞0.1元十万赞,飞速低价快

就像我们在某平台上传视频一样,到现在还不支持流式上传和文件上传,只支持表单上传,过大会导致视频闪退。 stream upload 表示上传成功,但是后台不识别。 这一次,某平台坏了。 直接带文件上传,通过了,上传进度100%,但还是被当做失败,无奈!

言归正传,压缩导出视频需要通过AVAssetExportSession来实现。 我们需要指定一个preset,判断是否支持这个preset。 只有支持才能使用。

我们这里设置的preset是AVAssetExportPreset640x480,压缩的比较多,需要根据服务器视频上传的支持程度来选择。 然后通过调用异步压缩和导入视频:

- (void)compressVideoWithVideoURL:(NSURL *)videoURL
                        savedName:(NSString *)savedName
                       completion:(void (^)(NSString *savedPath))completion {
  // Accessing video by URL
  AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
  // Find compatible presets by video asset.
  NSArray *presets = [AVAssetExportSession exportPresetsCompatibleWithAsset:videoAsset];
  // Begin to compress video
  // Now we just compress to low resolution if it supports
  // If you need to upload to the server, but server does't support to upload by streaming,
  // You can compress the resolution to lower. Or you can support more higher resolution.
  if ([presets containsObject:AVAssetExportPreset640x480]) {
    AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:videoAsset  presetName:AVAssetExportPreset640x480];
    NSString *doc = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    NSString *folder = [doc stringByAppendingPathComponent:@"HYBVideos"];
    BOOL isDir = NO;
    BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:folder isDirectory:&isDir];
    if (!isExist || (isExist && !isDir)) {
      NSError *error = nil;
      [[NSFileManager defaultManager] createDirectoryAtPath:folder
                                withIntermediateDirectories:YES
                                                 attributes:nil
                                                      error:&error];
      if (error == nil) {
        NSLog(@"目录创建成功");
      } else {
        NSLog(@"目录创建失败");
      }
    }
    NSString *outPutPath = [folder stringByAppendingPathComponent:savedName];
    session.outputURL = [NSURL fileURLWithPath:outPutPath];
    // Optimize for network use.
    session.shouldOptimizeForNetworkUse = true;
    NSArray *supportedTypeArray = session.supportedFileTypes;
    if ([supportedTypeArray containsObject:AVFileTypeMPEG4]) {
      session.outputFileType = AVFileTypeMPEG4;
    } else if (supportedTypeArray.count == 0) {
      NSLog(@"No supported file types");
      return;
    } else {
      session.outputFileType = [supportedTypeArray objectAtIndex:0];
    }
    // Begin to export video to the output path asynchronously.
    [session exportAsynchronouslyWithCompletionHandler:^{
      if ([session status] == AVAssetExportSessionStatusCompleted) {
        dispatch_async(dispatch_get_main_queue(), ^{
          if (completion) {
            completion([session.outputURL path]);
          }
        });
      } else {
        dispatch_async(dispatch_get_main_queue(), ^{
          if (completion) {
            completion(nil);
          }
        });
      }
    }];
  }
}

解决iOS8上视频录制导致的歪斜bug

iOS8有这样一个bug:弹出录制视频页面,回去后发现整个view是向下连的。 网上可能有很多解决方案,下面只是其中的一种:

扣扣空间说说浏览是怎么记录的 - qq名片赞0.1元十万赞,飞速低价快

[picker dismissViewControllerAnimated:YES completion:^{
    // for fixing iOS 8.0 problem that frame changed when open camera to record video.
    self.tabBarController.view.frame  = [[UIScreen mainScreen] bounds];
    [self.tabBarController.view layoutIfNeeded];
}];

提示:记得在选中或取消的代理中调用!

概括

每一个需求,你都可能会遇到坑,但再多的坑也抵不过对技术的执着追求,必须攻克所有的坑。 以前不知道怎么满足视频的需求,别人超越的时候,即使有坑,也不会告诉后来的人坑在哪里,他们往往只记得有坑他们的心。

今天分享给大家cf保存的录像怎么上传,帮助有困难的战友。 这里是一个标志:坑,请不要再跳坑了。 看完这篇文章,你是不是明白了什么? 如果你是做这个需求的,代码可以直接复制使用!

源代码

下载源码,记得star分享一下:

表哥的技术博客:【VideoCaptureDemo】

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 网站程序 扣扣空间说说浏览是怎么记录的 - qq名片赞0.1元十万赞,飞速低价快 https://www.wkzy.net/game/48352.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务