此命名空间包含音频和视频的高级录制和播放功能。
此库位于 CoreMedia、CoreAudio 和 CoreVideo 之上,但不为 UIKit 提供任何用户界面元素。 它是用于录制和播放音频和视频的工具包。
AV Foundation 广泛使用后台处理。 应用程序开发人员应注意确保线程安全,并在更新其用户界面时使用
InvokeOnMainThread
或其他技术。
某些常见任务不需要 AVFoundation:
表示
AVAsset
一个或多个媒体资产。 这些都保存在其
Tracks
财产中。 此外,
AVAsset
还包括元数据、跟踪分组和媒体首选项。
由于媒体资产(如电影)很大,因此实例化
AVAsset
不会自动加载文件。 查询属性时或通过对 或
LoadValuesAsynchronously
的显式调用
LoadValuesTaskAsync
加载属性。
捕获音频文件
应用程序开发人员必须首先与静态单一实例音频会话对象交互,该对象在应用和操作系统之间调节声音。 和
AVAudioSession
都
AudioSession
引用此相同的基础单一实例。 中的
AudioSession
大多数属性在 iOS 7 及更高版本中已弃用,应用程序开发人员应首选 中的
AVAudioSession
属性。
以下代码演示了准备音频录制的必要步骤。
var session = AVAudioSession.SharedInstance();
NSError error = null;
session.SetCategory(AVAudioSession.CategoryRecord, out error);
if(error != null){
Console.WriteLine(error);
return;
session.SetActive(true, out error);
if(error != null){
Console.WriteLine(error);
return;
//Declare string for application temp path and tack on the file extension
string fileName = string.Format("Myfile{0}.aac", DateTime.Now.ToString("yyyyMMddHHmmss"));
string tempRecording = NSBundle.MainBundle.BundlePath + "/../tmp/" + fileName;
Console.WriteLine(tempRecording);
this.audioFilePath = NSUrl.FromFilename(tempRecording);
var audioSettings = new AudioSettings() {
SampleRate = 44100.0f,
Format = MonoTouch.AudioToolbox.AudioFormatType.MPEG4AAC,
NumberChannels = 1,
AudioQuality = AVAudioQuality.High
//Set recorder parameters
NSError error;
recorder = AVAudioRecorder.Create(this.audioFilePath, audioSettings, out error);
if((recorder == null) || (error != null))
Console.WriteLine(error);
return false;
//Set Recorder to Prepare To Record
if(!recorder.PrepareToRecord())
recorder.Dispose();
recorder = null;
return false;
recorder.FinishedRecording += delegate (object sender, AVStatusEventArgs e) {
recorder.Dispose();
recorder = null;
Console.WriteLine("Done Recording (status: {0})", e.Status);
recorder.Record();
自定义播放
T:AVFoundation.Player
对象使用
AVPlayerItem
对象播放媒体。 封装
AVPlayerItem
的表示状态
AVAsset
。
自定义媒体捕获
许多捕获方案都对更易于使用的
UIImagePickerController
和
AVAudioRecorder
类感到满意。 更复杂的方案可以使用 AV Foundation 和相关
AVCaptureSession
类。
AVCaptureSession
通常会有一个或多个
AVCaptureInput
,以及一个或多个
AVCaptureOutput
。 每个都会
AVCaptureInput
为特定媒体类型 (音频或视频) 。
AVCaptureDevice
每个
T:AVFoundation.AVCaptureOuput
都将具有一个“缓冲区委托”,该委托将重复调用它可呈现、写入文件、分析等传入数据。
下图和源代码显示了 的初始化序列
AVCaptureFrames 示例
。
session = new AVCaptureSession () {
SessionPreset = AVCaptureSession.PresetMedium
// create a device input and attach it to the session
var captureDevice = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video);
if (captureDevice == null){
Console.WriteLine ("No captureDevice - this won't work on the simulator, try a physical device");
return false;
// If you want to cap the frame rate at a given speed, in this sample: 15 frames per second
NSError error = null;
captureDevice.LockForConfiguration(out error);
if(error != null){
Console.WriteLine(error);
captureDevice.UnlockForConfiguration();
return false;
captureDevice.ActiveVideoMinFrameDuration = new CMTime(1, 15);
captureDevice.UnlockForConfiguration();
var input = AVCaptureDeviceInput.FromDevice (captureDevice);
if (input == null){
Console.WriteLine ("No input - this won't work on the simulator, try a physical device");
return false;
session.AddInput (input);
// create a VideoDataOutput and add it to the sesion
var output = new AVCaptureVideoDataOutput () {
VideoSettings = new AVVideoSettings (CVPixelFormatType.CV32BGRA),
// configure the output
queue = new MonoTouch.CoreFoundation.DispatchQueue ("myQueue");
outputRecorder = new OutputRecorder ();
output.SetSampleBufferDelegate (outputRecorder, queue);
session.AddOutput (output);
session.StartRunning ();
请注意,
outputRecorder
是 的
AVCaptureVideoDataOutputSampleBufferDelegate
自定义子类。 在这种情况下,传入数据将转换为 ,
CIImage
CIColorInvert
在发送到显示器之前,将向其应用筛选器。
public class OutputRecorder : AVCaptureVideoDataOutputSampleBufferDelegate {
readonly CIColorInvert filter;
public OutputRecorder()
filter = new CIColorInvert();
public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
try {
var image = ImageFromSampleBuffer (sampleBuffer);
filter.Image = image;
// Do something with the image, we just stuff it in our main view.
AppDelegate.ImageView.BeginInvokeOnMainThread (delegate {
AppDelegate.ImageView.Image = UIImage.FromImage(filter.OutputImage);
// Although this looks innocent "Oh, he is just optimizing this case away"
// this is incredibly important to call on this callback, because the AVFoundation
// has a fixed number of buffers and if it runs out of free buffers, it will stop
// delivering frames.
sampleBuffer.Dispose ();
} catch (Exception e){
Console.WriteLine (e);
CIImage ImageFromSampleBuffer (CMSampleBuffer sampleBuffer)
// Get the CoreVideo image
using (var pixelBuffer = sampleBuffer.GetImageBuffer () as CVPixelBuffer){
// Lock the base address
pixelBuffer.Lock (0);
// Get the number of bytes per row for the pixel buffer
var baseAddress = pixelBuffer.BaseAddress;
int bytesPerRow = pixelBuffer.BytesPerRow;
int width = pixelBuffer.Width;
int height = pixelBuffer.Height;
var flags = CGBitmapFlags.PremultipliedFirst | CGBitmapFlags.ByteOrder32Little;
// Create a CGImage on the RGB colorspace from the configured parameter above
using (var cs = CGColorSpace.CreateDeviceRGB ())
using (var context = new CGBitmapContext (baseAddress,width, height, 8, bytesPerRow, cs, (CGImageAlphaInfo) flags))
using (var cgImage = context.ToImage ()){
pixelBuffer.Unlock (0);
return cgImage;
可以使用 直接将视频捕获到 文件中
AVCaptureMovieFileOutput
。 但是,此类没有可显示的数据,并且不能与
AVCaptureVideoDataOutput
同时使用。 相反,应用程序开发人员可以将它与 结合使用,
AVCaptureVideoPreviewLayer
如以下示例所示:
var session = new AVCaptureSession();
var camera = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video);
var mic = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Audio);
if(camera == null || mic == null){
throw new Exception("Can't find devices");
if(session.CanAddInput(camera)){
session.AddInput(camera);
if(session.CanAddInput(mic)){
session.AddInput(mic);
var layer = new AVCaptureVideoPreviewLayer(session);
layer.LayerVideoGravity = AVLayerVideoGravity.ResizeAspectFill;
layer.VideoGravity = AVCaptureVideoPreviewLayer.GravityResizeAspectFill;
var cameraView = new UIView();
cameraView.Layer.AddSublayer(layer);
var filePath = System.IO.Path.Combine( Path.GetTempPath(), "temporary.mov");
var fileUrl = NSUrl.FromFilename( filePath );
var movieFileOutput = new AVCaptureMovieFileOutput();
var recordingDelegate = new MyRecordingDelegate();
session.AddOutput(movieFileOutput);
movieFileOutput.StartRecordingToOutputFile( fileUrl, recordingDelegate);
应用程序开发人员应注意,函数
T:AVFoundation.AVCaptureMovieFileOutput.StopRecording
是异步的;例如,
FinishedRecording
开发人员应等到委托方法后再操作文件 (,然后再将其保存到包含
SaveToPhotosAlbum
或
WriteVideoToSavedPhotosAlbumAsync
) 的相册。
媒体文件写入、读取和转码
以下是 iOS 7 支持音频格式的官方列表:
-
AAC
-
Apple Lossless (ALAC)
-
A-law
-
IMA/ADPCM (IMA4)
-
线性 PCM
-
μ法
-
DVI/Intel IMA ADPCM
-
Microsoft GSM 6.10
-
AES3-2003
以及以下视频格式:
-
H.264 视频,最高 1.5 Mbps,640 x 480 像素,每秒 30 帧,Low-Complexity 版本的 H.264 基线配置文件,最高 160 Kbps、48 kHz、.m4v 立体声音频、.mp4 和 .mov 文件格式
-
H.264 视频,最大 768 Kbps,320 x 240 像素,30 帧/秒,基线配置文件高达 1.3 级,AAC-LC 音频高达 160 Kbps、48 kHz、.m4v、.mp4 和 .mov 文件格式的立体声音频
-
MPEG-4 视频,最大 2.5 Mbps,640 x 480 像素,30 帧/秒,简单配置文件,AAC-LC 音频最大 160 Kbps,48 kHz,.m4v 立体声音频,.mp4 和 .mov 文件格式
此列表不完整:例如,iPhone 5S 以 1280 x 720 本机捕获。
使用 读取媒体文件。
AVAssetReader
与许多 AV 基础类一样,这以异步方式提供数据。 属性
Outputs
包含
AVAssetReaderOutput
对象。
CopyNextSampleBuffer
这些对象上的 方法将定期调用,因为 处理
AVAssetReader
基础
Asset
。
可使用 编写媒体文件,
AVAssetWriter
但在媒体捕获会话中,更常见的是使用
AVAudioRecorder
、
AVCaptureMovieFileOutput
或 来完成
UIImagePickerController
。 的优点
AVAssetWriter
是它使用硬件编码。
实时识别
iOS 可以识别从视频设备捕获的条形码和人脸。
以下示例演示如何识别 QR 和 EAN13 条形码。 已配置 ,
AVCaptureSession
并将
T:AFoundation.AVCaptureMetadataOutput
添加到其中。 的
MyMetadataOutputDelegate
子类
AVCaptureMetadataOutputObjectsDelegate
分配给其
P:AVFoundation.AVCaptureMetadataObject.Delegate
属性。
必须将
MetadataObjectTypes
添加到
之后
AVCaptureMetadataOutput
设置数组。
此示例演示 的简单子类,该类
AVCaptureMetadataOutputObjectsDelegate
在识别条形码时引发事件。
session = new AVCaptureSession();
var camera = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video);
var input = AVCaptureDeviceInput.FromDevice(camera);
session.AddInput(input);
//Add the metadata output channel
metadataOutput = new AVCaptureMetadataOutput();
var metadataDelegate = new MyMetadataOutputDelegate();
metadataOutput.SetDelegate(metadataDelegate, DispatchQueue.MainQueue);
session.AddOutput(metadataOutput);
//Confusing! *After* adding to session, tell output what to recognize...
metadataOutput.MetadataObjectTypes = new NSString[] {
AVMetadataObject.TypeQRCode,
AVMetadataObject.TypeEAN13Code
//...etc...
public class MyMetadataOutputDelegate : AVCaptureMetadataOutputObjectsDelegate
public override void DidOutputMetadataObjects(AVCaptureMetadataOutput captureOutput, AVMetadataObject[] metadataObjects, AVCaptureConnection connection)
foreach(var m in metadataObjects)
if(m is AVMetadataMachineReadableCodeObject)
MetadataFound(this, m as AVMetadataMachineReadableCodeObject);
public event EventHandler<AVMetadataMachineReadableCodeObject> MetadataFound = delegate {};
语音合成
在 iOS 7 及更高版本中,AV Foundation 支持使用针对语言和区域设置本地化的语音进行语音合成。
在最简单的形式中,文本转语音只需两个类即可完成:
var ss = new AVSpeechSynthesizer();
var su = new AVSpeechUtterance("Microphone check. One, two, one two.") {
Rate = 0.25f
ss.SpeakUtterance(su);
维护
AVSpeechSynthesizer
的内部队列为
AVSpeechUtterance
。 应用程序开发人员无法访问队列,但可以使用 和
StopSpeaking
暂停或停止
PauseSpeaking
合成器。 事件(如
DidStartSpeechUtterance
或
WillSpeakRangeOfSpeechString
)是应用程序开发人员修改以前排队的序列的机会。