I have a big problem. I have a video streamer site. The site has public and private videos, private videos can be seen after purchase.
Here you can see the directory structure:
/public_html
|__/vendor
|__/src
|__/public
|__/product
|__/sample-video
|__/video.mp4
Well, as you can see the videos are located outside the public folder. The goal is to make them inaccessible directly.
Here is the twig:
<video id="myVideo">
<source src="/products/12?video=10&cache={{ random(50, 10000) }}" type="video/webm" />
<source src="/products/12?video=10&cache={{ random(50, 10000) }}" type="video/mp4" />
</video>
The video controller: https://pastebin.com/sne1mSHH
And the video stream logic: https://pastebin.com/2Sxd7Nqq
Here's the problem:
I'm going to the site. You switch between pages. Perfectly good. I go to a page with a video still good and after I start the video, the page is not good.. The page just loads and does nothing. I can't switch between pages anymore. I have to close the incognito mode and start a new session.
Until now I thought that the session lock was the problem, but I close the write session.
I tried opening the video in a new tab. Also the error is until the video stream is finished, the page does not handle the request.
So while the video is playing, while I can't send a new request. What else can I attach to make the error more transparent? Help pls!
I would personnally not use PHP to stream the video. The problem is that you'll have to many PHP processes locked for reading and streaming a big file instead of handling logic. You will also have a PHP timeout during this process.
Instead, I would use the Sendfile module:
You install an Apache module or other kind of Sendfile module for your web server, NGINX or whatever.
In PHP, you do the logic for the protection and just send a HTTP header to say you want Sendfile to handle the streaming. This way your PHP code stops running and its the web server that handles the transmission of the file.
Something like this:
<?php
if (has_access_to_the_video($file))
{
// Send the right HTTP headers.
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Content-type: ' . mime_content_type($file));
header('Content-Length: ' . filesize($file));
// Make sure you have X-Sendfile module installed on your server.
header('X-Sendfile: ' . $file);
exit;
}
else
{
// Generate your 403 error or whatever.
}
This may help you:
https://symfony.com/doc/current/components/http_foundation.html then search for sendfile
in the page.
https://www.h3xed.com/programming/how-to-use-x-sendfile-with-php-apache
For the <video>
tag, you are declaring two <source>
elements, one with type="video/webm"
and the other with type="video/mp4"
but both point to the same URL. In your PHP logic, I don't see any handling of the desired content type so your server is probably returning the same video file for both codecs and this is problematic. I would add the video content type in the URL and on the server side, do the internal redirection with Sendfile to the correct file (MP4, OGG, WEBM, etc). If the browser requests a WEBM
file and recieves a MP4 H.264
instead, I assume it will not load correctly.
It seems that MP4 H.264
is widely handled by know, so you could just stick with one source. See the current support here: