AVAssetReader和AVAssetWriter
来源:互联网 发布:java游戏服务端开发 编辑:程序博客网 时间:2024/05/13 05:03
AVAssetReader和AVAssetWriter
AVAssetReader和AVAssetWriter类可以让开发者直接处理媒体样本
AVAssetReader
AVAssetReader
用于从AVAssert
实例中读取媒体样本。每个AVAssetReader
对象在某个时刻只能和单个asset
关联,但这个asset
可包含多个tracks
。所以,在开始读取之前,必须给asset reader
指定一个AVAssetReaderOutput
的具体子类,来配置media data怎样读取。
可通过copyNextSampleBuffer
方法可以访问音频样本和视频帧。
AVAssetReaderOutput是一个抽象类,其有3个具体子类:
- AVAssetReaderTrackOutput从指定的AVAssetTrack中读取解码的媒体样本
- AVAssetReaderAudioMixOutput从多音频轨道中读取混合输出
- AVAssetReaderVideoCompositionOutput从多视频轨道中读取组合输出
注意:
AVAssetReader
只针对带有一个资源的媒体样本。如果需要同时从多个基于文件的资源中读取样本,可将它们组合到一个AVAsset
子类AVComposition
中
创建Asset Reader
NSError *outError;AVAsset *someAsset = <#AVAsset that you want to read#>;AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:someAsset error:&outError];BOOL success = (assetReader != nil);
注意:始终要检查返回的
asset reader
不为nil
,确保asset reader
初始化成功。否则,参数error
将会包含对应的错误信息
设置Asset Reader
的Outputs
在创建asset reader
之后,至少设置一个output
来接收读取的媒体数据。在设置outputs
时,要确保设置alwaysCopiesSampleData
为NO,这样的话,有改进性能的好处。
如果你仅仅想从一个或多个tracks
中读取媒体数据,并可能会把数据转换成另一种格式,就使用AVAssetReaderTrackOutput
类,为你想要从asset中读取的每个AVAssetTrack对象,使用一个单独的track ouput
对象。
使用asset reader
将audio track
解压缩为Linear PCM
,按如下方式设置track output
AVAsset *localAsset = assetReader.asset;// 获取读取的audio trackAVAssetTrack *audioTrack = [[localAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];//Linear PCM解压缩设置NSDictionary *decompressionAudioSettings = @{ AVFormatIDKey : [NSNumber numberWithUnsignedInt:kAudioFormatLinearPCM] };//使用audio track 和 解压缩设置创建outputAVAssetReaderOutput *trackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:decompressionAudioSettings];// 添加output到readerif ([assetReader canAddOutput:trackOutput]) [assetReader addOutput:trackOutput];
注意:要以本身存储的格式从特定的
asset track
中读取媒体数据,给outputSettings
参数传递nil
实际运用
音频波形图
《AV Foundation开发秘籍》中例子
读取资源的音频样本,返回NSData
数据,如下:
//从资源轨道中读取样本+ (NSData *)readAudioSamplesFromAsset:(AVAsset *)asset { NSError *error = nil; AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; if (!assetReader) { NSLog(@"Error creating asset reader: %@", [error localizedDescription]); return nil; } //获取资源中找到的第一个音频轨道 AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject]; /* *从资源轨道读取音频样本时使用的解压设置 *kAudioFormatLinearPCM 样本需要以未压缩的格式被读取 *little-endian字节序(小端序) *有符号整型 *16位 */ NSDictionary *outputSettings = @{ AVFormatIDKey : @(kAudioFormatLinearPCM), AVLinearPCMIsBigEndianKey : @NO, AVLinearPCMIsFloatKey : @NO, AVLinearPCMBitDepthKey : @(16) }; //创建trackOutput,作为AVAssetReader的输出 AVAssetReaderTrackOutput *trackOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:outputSettings]; [assetReader addOutput:trackOutput]; //开始预收取样本数据 [assetReader startReading]; NSMutableData *sampleData = [NSMutableData data]; while (assetReader.status == AVAssetReaderStatusReading) { CMSampleBufferRef sampleBuffer = [trackOutput copyNextSampleBuffer]; if (sampleBuffer) { //获取音频样本 CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sampleBuffer); //确定长度,并创建一个16位的带符号的整型数组来保存音频赝本 size_t length = CMBlockBufferGetDataLength(blockBufferRef); SInt16 sampleBytes[length]; CMBlockBufferCopyDataBytes(blockBufferRef, 0, length, sampleBytes); //数组内容附加在NSData实例后 [sampleData appendBytes:sampleBytes length:length]; //指定样本buffer已经处理和不可再继续使用 CMSampleBufferInvalidate(sampleBuffer); CFRelease(sampleBuffer); } } //数据读取成功 if (assetReader.status == AVAssetReaderStatusCompleted) { return sampleData; } else { NSLog(@"Failed to read audio samples from asset"); return nil; }}
效果如下:
AVAssetWriter
AVAssetWriter类将媒体数据从多个源写入指定文件格式的单个文件。不需要将asset writer对象与特定的asset相关联,但必须为要创建的每个输出文件使用单独的asset writer。由于asset writer
可以从多个源写入媒体数据,因此必须要为写入文件的每个track创建一个AVAssetWriterInput对象,每个AVAssetWriterInput
期望以CMSampleBufferRef对象形式接收数据,但如果你想要将CVPixelBufferRef类型对象添加到asset writer input
,就使用AVAssetWriterInputPixelBufferAdaptor类。
AVAssetWriter
用于对媒体资源进行编码并将其写入到容器文件中,比如一个MPEG-4
文件或QuickTime
文件。它由一个或多个AVAssetWriterInput
对象配置,用于附加将包含要写入容器的媒体样本的CMSampleBufferRef
对象。AVAssetWriterInput
被配置为可以处理指定的媒体类型,比如音频或视频,并且附加在其后的样本会在最终输出时生成一个独立的AVAssetTrack
。当使用一个配置了处理视频样本AVAssetWriterInput
时,开发者会经常用到一个专门的适配器对象AVAssetWriterInputPixelBufferAdaptor
。这个类在附加被包装为CVPixelBufferRef
对象的视频样本是提供最优性能。输入信息也可以通过使用AVAssetWriterInputGroup组成互斥的参数。这就让开发者能够创建特定资源,其中包含在播放时使用AVMediaSelectionGroup和AVMediaSelectionOption类选择的指定语言媒体轨道。
注意:与AVAssetExportSession相比,AVAssetWriter
明显的优势就是它对输出进行编码时能够进行更加细致的压缩设置控制。可以让开发者指定诸如关键帧间隔、视频比特率、H.264配置文件、像素宽高比和纯净光圈等设置
创建Asset Writer
创建Asset Writer
,需指定输出文件的URL
和要求的文件类型(file type
)。
下面的代码展示了如何创建一个asset writer
来创建一个QuickTime movie
:
NSError *outError;NSURL *outputURL = <#NSURL object representing the URL where you want to save the video#>;AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:outputURL fileType:AVFileTypeQuickTimeMovie error:&outError];BOOL success = (assetWriter != nil);
设置Asset Writer Inputs
为了asset writer能够写入media数据,必须设置至少一个asset writer input
例如,添加AVAssetWriterInput
self.assetWriterVideoInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo outputSettings:self.videoSettings]; self.assetWriterVideoInput.expectsMediaDataInRealTime = YES; if ([self.assetWriter canAddInput:self.assetWriterVideoInput]) { [self.assetWriter addInput:self.assetWriterVideoInput]; } else { NSLog(@"Unable to add video input."); return; }
AVAssetWriter的例子
objcn 在 iOS 上捕获视频一节有介绍使用AVAssetWriter来捕捉写入视频
资源
- Export
- AVAssetReader和AVAssetWriter
- AV Foundation系列(四)AVAssetReader和AVAssetWrite
- AVAssetReader+AVAssetReaderTrackOutput
- 翻译:AVAssetReader
- AVAssetReader 音频波形图
- AVAssetWriter写h264数据
- AVAssetWriter保存MP4(PBJVision)
- AVAssetWriter写入char*数据(video)
- iphone 通过AVAssetWriter将录像视频写到指定文件
- iphone 通过AVAssetWriter将录像视频写到指定文件
- AVAssetWriter finishWritingWithCompletionHandler函数没有正常执行的原因
- AVAssetWriter 输出视频文件在ios8上的结束
- 从 将pcm数据通过AVAssetWriter输出成aac
- AVAssetWriter 输出视频文件在ios8上的结束
- 关于AVAssetWriter,AVAssetWriterInput报错Cannot call method when status is 2的问题记录
- iOS AVAssetWriter 实现高分辨率录制视频,生成低体积的视频文件
- [绍棠] GPUImageMovieWriter 无法2次录像 报错:[AVAssetWriter startWriting] Cannot call method when status is 3
- . 和 ->
- 面试题36:数组中的逆序对
- 网站中返回上级的处理
- 【Qt5】QString与string,int转换
- Servlet 知识点(一) -- 异步请求Servlet
- LOL多人在线游戏
- AVAssetReader和AVAssetWriter
- mongo(2)
- 【脚本语言系列】关于Python结构化文本文件处理csv,你需要知道的事
- 前后台时间类型数据的处理
- Fire And Motion:聚焦前进,避免当炮灰
- java的Applet编写的日历小工具
- C++随记(八)---存储持续性、作用域和链接性
- 如何优雅地从浏览器打开本地应用
- IIS默认网站自动跳转到虚拟目录的几种方法