Home  >  Q&A  >  body text

How to stream http mjpg over https using php proxy

<p>I have this php script which is supposed to load an mjpg stream over HTTP and output over HTTPS. However, all it produces is a broken image: </p> <pre class="brush:php;toolbar:false;"><?php function proxyMjpegStream($url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_BUFFERSIZE, 8192); header("Content-Type: multipart/x-mixed-replace; boundary=myboundary"); curl_exec($ch); curl_close($ch); } // Get the URL of the MJPEG stream to proxy if (isset($_GET['url'])) { $mjpegUrl = $_GET['url']; // Validate that the URL is a valid HTTP source if (filter_var($mjpegUrl, FILTER_VALIDATE_URL) && strpos($mjpegUrl, 'http://') === 0) { proxyMjpegStream($mjpegUrl); exit; } } // Invalid or missing MJPEG URL parameter header("HTTP/1.0 400 Bad Request"); echo "Invalid MJPEG URL"; ?></pre></p>
P粉835428659P粉835428659384 days ago478

reply all(2)I'll reply

  • P粉588152636

    P粉5881526362023-09-04 15:45:35

    This isn't really the answer to the question, Anas already covered this, but it's worth mentioning anyway and doesn't fit in the comments.

    You will have trouble writing code blocks like this:

     // Get the URL of the MJPEG stream to proxy
     if (isset($_GET['url'])) {
       $mjpegUrl = $_GET['url'];
    
       // Validate that the URL is a valid HTTP source
       if (filter_var($mjpegUrl, FILTER_VALIDATE_URL) && strpos($mjpegUrl, 'http://') === 0) {
         proxyMjpegStream($mjpegUrl);
         exit;
       }
     }
    
      // Invalid or missing MJPEG URL parameter
      header("HTTP/1.0 400 Bad Request");
      echo "Invalid MJPEG URL";
    

    If you continue to defer error conditions to the end and include non-error conditions in if(){} blocks, you will run into two problems.

    1. The conditions that trigger errors are becoming increasingly disconnected from where error messages are generated.
    2. Your "path to happiness" code is buried deeper and deeper in nested if(){} blocks, known as the arrow anti-pattern.

    You can reformat:

    if( good ) {
      if( also good ) {
        do_thing();
        exit();
      } else {
        raise_error('also bad');
      }
    }
    raise_error('bad');

    To:

    if( ! good ) {
      raise_error('bad');
    }
    if( ! also good ) {
      raise_error('also bad');
    }
    do_thing();

    This is not a hard and fast rule, but keeping it in mind can help avoid writing disjointed or confusing blocks of code, or blocks of code that end up extending to the right side of the page.

    reply
    0
  • P粉523625080

    P粉5236250802023-09-04 09:43:59

    After some research, you can use the following function to execute a stream in curl:

    curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'streamCallback');

    And create a callback function:

    function streamCallback($curl, $data) {
        // Process the received data
        echo $data;
    
        // Return the length of the data processed
        return strlen($data);
    }

    Your code works fine, but after 30 seconds your stream will end because you set curl_setopt($ch, CURLOPT_TIMEOUT, 30);

    My recommendation for streaming URLs is to use fopen() since cURL is primarily designed for making HTTP requests to get static content. MJPEG streams are dynamic and new frames are sent continuously.

    By default, cURL sets a timeout for each request. If the server takes a long time to send frames, the request may timeout, resulting in an interruption in the stream or an error message.

    You can use the fopen() function for the best experience. Here is an example using streams and fopen.

    <?php
    $videoUrl = 'http://74.142.49.38:8000/axis-cgi/mjpg/video.cgi';
    
    // Set the appropriate headers for MJPG
    header('Content-Type: multipart/x-mixed-replace; boundary=myboundary');
    
    // Continuously fetch and display frames
    while (true) {
        // Open a connection to the video stream
        $stream = fopen($videoUrl, 'rb');
    
        // Check if the stream is valid
        if (!$stream) {
            die('Error opening stream');
        }
    
        // Read and display each frame
        while ($frame = fread($stream, 4096)) {
            // Display the frame
            echo $frame;
    
            // Flush the output buffer
            ob_flush();
            flush();
        }
    
        // Close the stream
        fclose($stream);
    }
    ?>

    reply
    0
  • Cancelreply