如何从iPhone相机获取实时视频流并将其发送到服务器?

32

我正在使用 AVCaptureSession 捕获视频并从 iPhone 相机获取实时帧,但如何通过多路复用来发送图像和声音到服务器,并且如何使用 ffmpeg 完成此任务呢?如果有任何关于 ffmpeg 的教程或示例,请在此分享。


1
我假设你已经在记录MOV/MP4“块”文件。你可以使用我写的一个旧项目ffstream(由某人分叉)来流式传输这些文件。请记住,您必须保持单调递增的时间。换句话说,每个MOV/MP4的起始时间必须相同。通过这种方式,所有1+N个文件将在开头有“空白”空间,并且ffmpeg中mov.c生成的时间戳将是正确的。您可以使用UDP/TCP上的RTSP/RTP或使用ffmpeg的librtmp插件进行流式传输。 - Steve McFarlin
@SteveMcFarlin,你能帮我学习如何将本地流发送到服务器吗?也就是说,如何将流作为块发送。 - Rahul Juyal
3个回答

27
我正在实现一个AVCaptureSession,它有一个回调的代理,在每一帧上运行。该回调将每一帧发送到服务器上,服务器有一个自定义设置来接收它。
以下是流程:

http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/03_MediaCapture.html#//apple_ref/doc/uid/TP40010188-CH5-SW2

这里是一些代码:

// make input device

NSError *deviceError;

AVCaptureDevice *cameraDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

AVCaptureDeviceInput *inputDevice = [AVCaptureDeviceInput deviceInputWithDevice:cameraDevice error:&deviceError];

// make output device

AVCaptureVideoDataOutput *outputDevice = [[AVCaptureVideoDataOutput alloc] init];

[outputDevice setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

// initialize capture session

AVCaptureSession *captureSession = [[[AVCaptureSession alloc] init] autorelease];

[captureSession addInput:inputDevice];

[captureSession addOutput:outputDevice];

// make preview layer and add so that camera's view is displayed on screen

AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer    layerWithSession:captureSession];
previewLayer.frame = view.bounds;
[view.layer addSublayer:previewLayer];

// go!

[captureSession startRunning];

然后输出设备的代理(这里是self)必须实现回调函数:

-(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection

{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer( sampleBuffer );

CGSize imageSize = CVImageBufferGetEncodedSize( imageBuffer );

// also in the 'mediaSpecific' dict of the sampleBuffer

   NSLog( @"frame captured at %.fx%.f", imageSize.width, imageSize.height );

    }

Sending raw frames or individual images will never work well enough for you (because of the amount of data and number of frames). Nor can you reasonably serve anything from the phone (WWAN networks have all sorts of firewalls). You'll need to encode the video, and stream it to a server, most likely over a standard streaming format (RTSP, RTMP). There is an H.264 encoder chip on the iPhone >= 3GS. The problem is that it is not stream oriented. That is, it outputs the metadata required to parse the video last. This leaves you with a few options.
1) Get the raw data and use FFmpeg to encode on the phone (will use a ton of CPU and battery).
2) Write your own parser for the H.264/AAC output (very hard).
3) Record and process in chunks (will add latency equal to the length of the chunks, and drop around 1/4 second of video between each chunk as you start and stop the sessions).

1
到目前为止,我已经完成了,感谢您的回复。我的问题是在那之后,我如何将iPhone上的音频和视频帧发送到服务器。 - Rahul Juyal
2
我知道这是老话题了,但我卡在了这个话题的服务器端。你是如何配置你的服务器来处理图像帧流的? - Siriss
3
开发者.apple.com页面未找到。 - AechoLiu

4

点此查看,再点此

尝试使用AV Foundation框架捕获视频并进行HTTP流媒体传输至服务器。

另外,请查看下面的Stack Overflow帖子

(此帖子链接在此处)

您可能已经知道...

 1) How to get compressed frames and audio from iPhone's camera?

您无法实现这个功能。AVFoundation API在各个方面都已经进行了阻止。我甚至尝试了命名管道和其它一些诡秘的Unix命令,但都没有成功。您别无选择,只能将其写入文件中。在您提供的链接中,有用户建议设置回调函数以传递编码帧,但据我所知,对于H.264流,这是不可能的。捕获委托将提供以特定像素格式编码的图像。编码是由电影编写器和AVAssetWriter完成的。
 2) Encoding uncompressed frames with ffmpeg's API is fast enough for
 real-time streaming?

是的,它可以。但是你需要使用libx264,这将让你进入GPL领域。这与应用商店不太兼容。

出于效率原因,我建议使用AVFoundation和AVAssetWriter。


4
有一个长故事和一个短故事。
这是短故事: 请查看https://github.com/OpenWatch/H264-RTSP-Server-iOS
这是一个起点。
您可以获取它并查看如何提取帧。这是一个小而简单的项目。
然后,您可以查看kickflip,它具有特定功能“encodedFrame”,一旦编码帧到达此点,就会回调它,从此处可以对其进行任何操作,通过websocket发送。有一堆非常难读的MPEG原子可供阅读。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接