web-dev-qa-db-fra.com

Comment obtenir le flux vidéo en temps réel de la caméra iphone et l'envoyer au serveur?

J'utilise AVCaptureSession pour capturer la vidéo et obtenir la trame en temps réel de la caméra de l'iPhone, mais comment puis-je l'envoyer au serveur avec multiplexage de la trame et du son et comment utiliser ffmpeg pour terminer cette tâche, si quelqu'un a un didacticiel à propos de ffmpeg ou de tout autre exemple, veuillez partager ici.

30
Ron

La façon dont je le fais est d'implémenter un AVCaptureSession, qui a un délégué avec un rappel qui s'exécute sur chaque trame. Ce rappel envoie chaque trame sur le réseau au serveur, qui a une configuration personnalisée pour la recevoir.

Voici le flux:

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

Et voici un peu de code:

// 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];

Ensuite, le délégué du périphérique de sortie (ici, self) doit implémenter le rappel:

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

    }

L'envoi d'images brutes ou d'images individuelles ne fonctionnera jamais assez bien pour vous (en raison de la quantité de données et du nombre d'images). Vous ne pouvez pas non plus servir quoi que ce soit à partir du téléphone (les réseaux WWAN ont toutes sortes de pare-feu). Vous devrez encoder la vidéo et la diffuser sur un serveur, très probablement sur un format de streaming standard (RTSP, RTMP). Il y a une puce d'encodeur H.264 sur l'iPhone> = 3GS. Le problème est qu'il n'est pas orienté flux. Autrement dit, il génère les métadonnées nécessaires pour analyser la vidéo en dernier. Cela vous laisse quelques options.

1) Obtenez les données brutes et utilisez FFmpeg pour encoder sur le téléphone (utilisera une tonne de CPU et de batterie).

2) Écrivez votre propre analyseur pour la sortie H.264/AAC (très difficile).

3) Enregistrez et traitez en morceaux (ajoutera une latence égale à la longueur des morceaux et déposez environ 1/4 de seconde de vidéo entre chaque morceau lorsque vous démarrez et arrêtez les sessions).

24
Jerry Thomsan

Regardez ici , et ici

Essayez de capturer des vidéos à l'aide du framework AV Foundation. Téléchargez-le sur votre serveur avec le streaming HTTP.

Consultez également une pile un autre message de débordement de pile ci-dessous

(Le post ci-dessous a été trouvé sur ce lien ici)

Vous savez probablement déjà ...

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

Tu ne peux pas faire ça. L'API AVFoundation a empêché cela sous tous les angles. J'ai même essayé des pipes nommées et quelques autres foo unix sournois. Pas de chance. Vous n'avez pas d'autre choix que de l'écrire dans un fichier. Dans votre publication liée, un utilisateur suggère de configurer le rappel pour fournir des images codées. Pour autant que je sache, cela n'est pas possible pour les flux H.264. Le délégué de capture fournira des images encodées dans un format de pixel spécifique. Ce sont les Movie Writers et AVAssetWriter qui font l'encodage.

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

Oui, ça l'est. Cependant, vous devrez utiliser libx264 qui vous permet d'accéder au territoire GPL. Ce n'est pas exactement compatible avec l'App Store.

Je suggère d'utiliser AVFoundation et AVAssetWriter pour des raisons d'efficacité.

4
Comradsky

Il y a une longue et une courte histoire.

C'est le court: allez voir https://github.com/OpenWatch/H264-RTSP-Server-iOS

c'est un point de départ.

vous pouvez l'obtenir et voir comment il extrait le cadre. Il s'agit d'un petit projet simple.

Ensuite, vous pouvez regarder kickflip qui a une fonction spécifique "encodedFrame", ses onces rappelées et la trame encodée arrivent à partir de ce point, vous pouvez faire ce que vous voulez avec, envoyer via websocket. Il y a un tas de code très dur disponible pour lire les atomes MPEG

3
Zeev's Glozman