web-dev-qa-db-ja.com

iPhoneカメラからリアルタイムビデオストリームを取得してサーバーに送信する方法は?

AVCaptureSessionを使用してビデオをキャプチャし、iPhoneカメラからリアルタイムフレームを取得していますが、フレームとサウンドを多重化してサーバーに送信するにはどうすればよいですか。また、チュートリアルがある場合、ffmpegを使用してこのタスクを完了する方法を教えてください。 ffmpegやその他の例については、こちらで共有してください。

30
Ron

私が行っている方法は、AVCaptureSessionを実装することです。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];

次に、出力デバイスのデリゲート(ここでは、自己)がコールバックを実装する必要があります。

-(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 );

    }

生のフレームまたは個別の画像を送信しても、データ量やフレーム数が少ないため、十分に機能しません。電話から何かを合理的に提供することもできません(WWANネットワークにはあらゆる種類のファイアウォールがあります)。ビデオをエンコードし、サーバーにストリーミングする必要があります。おそらく、標準のストリーミング形式(RTSP、RTMP)を介してストリーミングします。 iPhoneにH.264エンコーダチップがあります> = 3GS。問題は、ストリーム指向ではないことです。つまり、最後にビデオを解析するために必要なメタデータを出力します。これにはいくつかのオプションがあります。

1)生データを取得し、FFmpegを使用して電話でエンコードします(大量のCPUとバッテリーを使用します)。

2)H.264/AAC出力用の独自のパーサーを作成します(非常に難しい)。

3)チャンクで記録して処理します(チャンクの長さに等しいレイテンシが追加され、セッションを開始および停止すると、各チャンク間でビデオの約1/4秒がドロップされます)。

24
Jerry Thomsan

ここを見てそしてここを

AV Foundationフレームワークを使用してビデオをキャプチャしてみてください。 HTTPストリーミングでサーバーにアップロードします。

また、以下のスタックの別のスタックオーバーフローポストをチェックアウトしてください

(以下の投稿はこのリンクで見つかりました)

あなたはおそらくすでに知っています...

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

これはできません。 AVFoundation APIはこれをあらゆる角度から防ぎました。名前付きパイプや他の卑劣なunix fooも試しました。そのような運はありません。ファイルに書き込む以外に選択肢はありません。リンクされた投稿で、エンコードされたフレームを配信するようにコールバックを設定することをユーザーに提案します。私の知る限り、これはH.264ストリームでは不可能です。キャプチャデリゲートは、特定のピクセル形式でエンコードされた画像を配信します。エンコードを行うのは、ムービーライターとAVAssetWriterです。

 2) Encoding uncompressed frames with ffmpeg's API is fast enough for
 real-time streaming?

はい、そうです。ただし、GPL領域に入るlibx264を使用する必要があります。これはアプリストアと完全に互換性があるわけではありません。

効率上の理由から、AVFoundationとAVAssetWriterを使用することをお勧めします。

4
Comradsky

それには、長い話と短い話があります。

これは短いものです: https://github.com/OpenWatch/H264-RTSP-Server-iOS を見てください

これが出発点です。

あなたはそれを取得し、彼がどのようにフレームを抽出するかを見ることができます。これは小さくてシンプルなプロジェクトです。

次に、特定の関数「encodedFrame」を備えたキックフリップを確認し、一度コールバックすると、エンコードされたフレームがこの時点から到着し、WebSocket経由で送信して、やりたいことを実行できます。 mpegアトムを読み取るのに利用できる非常にハードなコードがたくさんあります

3
Zeev's Glozman