Upload live streaming video from iPhone like Ustream or Qik

后端 未结 3 1591
既然无缘
既然无缘 2020-11-29 14:55

How to live stream videos from iPhone to server like Ustream or Qik? I know there\'s something called Http Live Streaming from Apple, but most resources I found only talks a

3条回答
  •  一整个雨季
    2020-11-29 15:21

    There isn't a built-in way to do this, as far as I know. As you say, HTTP Live Streaming is for downloads to the iPhone.

    The way I'm doing it is to implement an AVCaptureSession, which has a delegate with a callback that's run on every frame. That callback sends each frame over the network to the server, which has a custom setup to receive it.

    Here's the flow: https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html#//apple_ref/doc/uid/TP40010188-CH5-SW2

    And here's some 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];
    

    Then the output device's delegate (here, self) has to implement the callback:

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

    EDIT/UPDATE

    Several people have asked how to do this without sending the frames to the server one by one. The answer is complex...

    Basically, in the didOutputSampleBuffer function above, you add the samples into an AVAssetWriter. I actually had three asset writers active at a time -- past, present, and future -- managed on different threads.

    The past writer is in the process of closing the movie file and uploading it. The current writer is receiving the sample buffers from the camera. The future writer is in the process of opening a new movie file and preparing it for data. Every 5 seconds, I set past=current; current=future and restart the sequence.

    This then uploads video in 5-second chunks to the server. You can stitch the videos together with ffmpeg if you want, or transcode them into MPEG-2 transport streams for HTTP Live Streaming. The video data itself is H.264-encoded by the asset writer, so transcoding merely changes the file's header format.

提交回复
热议问题