SCRecorder

https://github.com/rFlex/SCRecorder

An easy Vine/Instagram like video and/or audio recorder class with Core Image filters support.

类似于 Vine/Instagram 视频或者音频的录制的类,使用 Core Image 作为滤镜。

A Vine/Instagram like audio/video recorder in Objective-C.

In short, here is a short list of the cool things you can do:

  • Record multiple video segments
  • Remove any record segment that you don't want
  • Display the result into a convenient video player
  • Add a video filter using Core Image
  • Merge and export the video using fine tunings that you choose

简单而言,他可以做到如下这些:

* 记录分段的录像

* 移除你所不需要的录像片段

* 可以方便的显示你编辑的视频

* 使用 Core Image 当做视频滤镜

* 合并并输出你所选择的视频

These classes allow the recording of a video with pause/resume function. Although the project was initially made for the sake of taking videos only, you can now take pictures as well with some very useful utility functions that make the project totally suitable for a standalone camera engine. They are highly configurable, all the classes provide a lot of properties so we are quite sure that it should meet your needs :).

这些类允许你录制的时候暂停以及恢复。虽然这个项目是专门用来处理视频的,但你也可以用它来处理照相机功能。它高度定制,所有的类都提供了大量的属性供你定制:)。

Examples for iOS are provided.

Want something easy to create your filters in this project? Checkout https://github.com/rFlex/CoreImageShop

Framework needed:

  • CoreVideo
  • AudioToolbox
  • GLKit

想让滤镜使用起来更方便?看看这个地方https://github.com/rFlex/CoreImageShop

需要的框架:

* CoreVideo

* AudioToolbox

* GlKit (OpenGLES)

Podfile

If you are using cocoapods, you can use this project with the following Podfile

platform :ios, '7.0'
pod "SCRecorder", "~> 2.0"

Getting started

SCRecorder is the main class that connect the inputs and outputs together. It will handle all the underlying AVFoundation stuffs.

// Create the recorder
SCRecorder *recorder = [SCRecorder recorder]; // Set the sessionPreset used by the AVCaptureSession
recorder.sessionPreset = AVCaptureSessionPresetHigh; // Listen to some messages from the recorder!
recorder.delegate = self; // Initialize the audio and video inputs using the parameters set in the SCRecorder
[recorder openSession: ^(NSError *sessionError, NSError *audioError, NSError *videoError, NSError *photoError) {
// Start the flow of inputs
[recorder startRunningSession: ^{
// Session is now started! }];
}];

Begin the recording

The second class we are gonna see is SCRecordSession, which is the class that process the inputs and append them into an output file. A record session can contains one or several record segments. A record segment is just a continuous video and/or audio file, represented as a NSURL. It starts when you hold the record button and end when you release it, if you implemented the record button the same way as instagram and vine did. When you end the SCRecordSession, it will merge the record segments (if needed). If the record is started on the SCRecorder, setting a SCRecordSession inside it will automatically start a record segment. If you don't want this to happen, you must remove the SCRecordSession from the SCRecorder while manipulating it.

// Creating the recordSession
SCRecordSession *recordSession = [SCRecordSession recordSession]; // Before setting it to the recorder, you can configure many things on the recordSession,
// like the audio/video compression, the maximum record duration time, the output file url... recorder.recordSession = recordSession; [recorder record];

Finishing the record

You can call endSession on the SCRecordSession to stop the current recording segment, merge every record segments and delete the underlying files used by the record segments. Only one file will be remaining after calling this method, which will be contained in the outputUrl. Note that this property is automatically generated, but you can set one if you want to record to a specific location.

SCRecordSession *recordSession = recorder.recordSession;
recorder.recordSession = nil; [recordSession endSession:^(NSError *error) {
if (error == nil) {
NSURL *fileUrl = recordSession.outputUrl;
// Do something with the output file :)
} else {
// Handle the error
}
}];

And start doing the cool stuffs!

// You can read each record segments individually
SCRecordSession *recordSession = recorder.recordSession;
for (NSURL *recordSegment in recordSession.recordSegments) {
// Do something cool with it
} // You can remove a record segment at anytime
// Setting deleteFile to YES will delete the underlying file
[recordSession removeSegmentAtIndex:1 deleteFile:YES]; // Record a square video like Vine/Instagram
recordSession.videoSizeAsSquare = YES; // Or add a random record segment that you made before
[recordSession insertSegment:fileUrl atIndex:0]; // You can read the recordSegments easily without having to merge them
AVAsset *recordSessionAsset = [recordSession assetRepresentingRecordSegments]; // Record in slow motion!
recordSession.videoTimeScale = 4; // Get a dictionary representation of the record session
// And save it somewhere, so you can use it later!
NSDictionary *dictionaryRepresentation = [recordSession dictionaryRepresentation];
[[NSUserDefaults standardUserDefaults] setObject:dictionaryRepresentation forKey:@"RecordSession"]; // Restore a record session from a saved dictionary representation
NSDictionary *dictionaryRepresentation = [[NSUserDefaults standardUserDefaults] objectForKey:@"RecordSession"];
SCRecordSession *recordSession = [SCRecordSession recordSession:dictionaryRepresentation]; // Limiting the record duration
// When the record reaches this value, the recorder will remove the recordSession and call
// recorder:didCompleteRecordSession: on the SCRecorder delegate. It's up to you
// to do whatever you want with the recordSession after (the recordSegments won't be merge nor deleted, but
// the current recordSegment will be finished automatically)
recordSession.suggestedMaxRecordDuration = CMTimeMakeWithSeconds(7, 10000); // Taking a picture
[recorder capturePhoto:^(NSError *error, UIImage *image) {
if (image != nil) {
// Do something cool with it!
}
}]; // Display your recordSession
SCVideoPlayerView *videoPlayer = [[SCVideoPlayerView alloc] init];
[videoPlayer.player setItemByAsset:recordSessionAsset]; videoPlayer.frame = self.view.bounds;
[self.view addSubView:videoPlayer];
[videoPlayer.player play]; // Add a filter, in real time
CIFilter *blackAndWhite = [CIFilter filterWithName:@"CIColorControls" keysAndValues:@"inputBrightness", @0.0, @"inputContrast", @1.1, @"inputSaturation", @0.0, nil];
SCFilter *filter = [[SCFilter alloc] initWithCIFilter:blackAndWhite];
videoPlayer.player.filterGroup = [SCFilterGroup filterGroupWithFilter:filter]; // Import a filter made using CoreImageShop
NSURL *savedFilterGroupUrl = ...;
videoPlayer.player.filterGroup = [SCFilterGroup filterGroupWithContentsOfUrl:savedFilterGroupUrl]; // Export your final video with the filter
SCAssetExportSession exportSession = [[SCAssetExportSession alloc] initWithAsset:recordSessionAsset];
exportSession.keepVideoSize = YES;
exportSession.sessionPreset = SCAssetExportSessionPresetHighestQuality;
exportSession.fileType = AVFileTypeMPEG4;
exportSession.outputUrl = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingString:@"_output.mp4"]];
exportSession.filterGroup = [SCFilterGroup filterGroupWithFilter:filter]; [exportSession exportAsynchronouslyWithCompletionHandler:^ {
NSError *error = exportSession.error; // Etc...
}]

[翻译] SCRecorder的更多相关文章

  1. 《Django By Example》第五章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者@ucag注:大家好,我是新来的翻译, ...

  2. 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...

  3. [翻译]开发文档:android Bitmap的高效使用

    内容概述 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently",包括大尺寸Bitmap的高效加载,图片的异步加载和数据缓存 ...

  4. 【探索】机器指令翻译成 JavaScript

    前言 前些时候研究脚本混淆时,打算先学一些「程序流程」相关的概念.为了不因太枯燥而放弃,决定想一个有趣的案例,可以边探索边学. 于是想了一个话题:尝试将机器指令 1:1 翻译 成 JavaScript ...

  5. 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...

  6. 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...

  7. 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...

  8. 【翻译】Awesome R资源大全中文版来了,全球最火的R工具包一网打尽,超过300+工具,还在等什么?

    0.前言 虽然很早就知道R被微软收购,也很早知道R在统计分析处理方面很强大,开始一直没有行动过...直到 直到12月初在微软技术大会,看到我软的工程师演示R的使用,我就震惊了,然后最近在网上到处了解和 ...

  9. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第一章:创建基本的MVC Web站点

    在这一章中,我们将学习如何使用基架快速搭建和运行一个简单的Microsoft ASP.NET MVC Web站点.在我们马上投入学习和编码之前,我们首先了解一些有关ASP.NET MVC和Entity ...

随机推荐

  1. python如何帮我在投资中获取更高收益

    搞技术的大都比较纯粹,比较实在,除了工资之外基本就没有别的收入了(少部分人能接外包赚外块).或许是迫于生活的压力,或许是不甘于固定的工资,或许是出于技术人骨子里的好奇,亦或是这几年关于理财投资的大力宣 ...

  2. C++中内联函数

    目录 什么是内联函数 如何使函数内联 为什么要使用内联函数 inline函数的优缺点分析 什么时候该使用内联函数 正文 在C语言中,我们使用宏定义函数这种借助编译器的优化技术来减少程序的执行时间,那么 ...

  3. ABP实战--集成Ladp/AD认证

    参照Hunter的ABP-Zero模块中用户管理部分. 由于我们公司的各系统基本都是AD帐号登录的,所以我们需扩展ABP的AuthenticationSource. 添加MyLdapAuthentic ...

  4. 通过spark-sql快速读取hive中的数据

    1 配置并启动 1.1 创建并配置hive-site.xml 在运行Spark SQL CLI中需要使用到Hive Metastore,故需要在Spark中添加其uris.具体方法是将HIVE_CON ...

  5. Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )

    通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括: ① __getattr__(self, name): 访问不存在的属性时调用 ② __getattribute_ ...

  6. hadoop学习笔记(五):HDFS Shell命令

    一.HDFS文件命令 以下是比较重要的一些命令: [root@master01 hadoop]# hadoop fs -ls / //查看根目录下的所有文件 [root@master01 hadoop ...

  7. 10.Set 和 Map 数据结构

    Set 和 Map 数据结构 Set 和 Map 数据结构 Set 基本用法 ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来 ...

  8. NSLog演化

    使用下面代码打印行号,功能函数,以及要打印的内容 #if DEBUG #define MBLog(format, ...) NSLog((@"%s--[Line:%d]--" fo ...

  9. 【转】到底什么时候应该用MQ

    原文地址:http://zhuanlan.51cto.com/art/201704/536407.htm 一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题 ...

  10. vs中发布WebSever时启用HTTP-POST和HTTP-GET这两种协议

    一.问题介绍 在vs中建立一个websever项目时候默认是禁用HTTP-POST和HTTP-GET这两种协议的.但是如果你是在本机上去调试或者是在iis中浏览都会有HTTP-POST这种方式,因为这 ...