قصد داریم در این آموزش به شما نحوه استریم ویدیو در PHP یا همان پخش زنده ویدیو بدون دانلود کامل آن را در وب (video stream) را نشان بدیم.
قبل از شروع مقاله آموزشی استریم ویدیو در PHP , نیاز است مفهوم Stream را درک کنیم.
استریمینگ یا لایو استریم تکنیکی است که به وسیله آن می توان یک فایل چند رسانهای مانند صدا ویا تصویر ویدئویی را بدون این که احتیاج به دانلود همه فایل باشد، بر روی اینترنت به صورت لحظه ای از نقطه زمان مورد درخواست مشاهده کرد.
به عبارت دقیق تر برای مشاهده یک ویدئو معمولی، بایستی ابتدا کل فایل در سیستم بارگزاری شده و سپس نمایش داده شود. اما ویدئو استریمینگ به شما اجازه می دهد که از محتوا قبل از اینکه تمام فایل دانلود شود، شروع به استفاده و مشاهده کنید.
سایت های بزرگ اشتراک ویدیو مثلا یوتیوب و آپارات از این قابلیت Video Stream استفاده می کنند تا ما بدون نیاز به انتظار برای لود کل ویدیو, آن را پخش کنیم.
امروزه سرویسهای میزبانی ویدئو با استفاده از استانداردهای رایج از جمله RTMP و HLS به صورت هم زمان ویدیو را دریافت و نمایش میدهد؛ به گونهای که طی این فرآیند، استریمهای فایل ویدئویی به بخش های بسیار کوتاه (TS) چند ثانیه ای تقسیم شده و پلیر به جای دریافت کل فایل به صورت تکه های مجزا دریافت میکند.
روش های زیادی برای استریم ویدیو در PHP وجود دارد یکی از این روش های بسیار قدیمی که به تنهایی کاربردی ندارد و یکسری عملیات دیگر نیاز است, ست کردن هدر و خواندن فایل با توابع fopen است که یک کلاس ساده از آن را قرار دادیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
<?php /** * Description of VideoStream */ class VideoStream { private $path = ""; private $stream = ""; private $buffer = 102400; private $start = -1; private $end = -1; private $size = 0; function __construct($filePath) { $this->path = $filePath; } /** * Open stream */ private function open() { if (!($this->stream = fopen($this->path, 'rb'))) { die('Could not open stream for reading'); } } /** * Set proper header to serve the video content */ private function setHeader() { ob_get_clean(); header("Content-Type: video/mp4"); header("Cache-Control: max-age=2592000, public"); header("Expires: ".gmdate('D, d M Y H:i:s', time()+2592000) . ' GMT'); header("Last-Modified: ".gmdate('D, d M Y H:i:s', @filemtime($this->path)) . ' GMT' ); $this->start = 0; $this->size = filesize($this->path); $this->end = $this->size - 1; header("Accept-Ranges: 0-".$this->end); if (isset($_SERVER['HTTP_RANGE'])) { $c_start = $this->start; $c_end = $this->end; list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); if (strpos($range, ',') !== false) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $this->start-$this->end/$this->size"); exit; } if ($range == '-') { $c_start = $this->size - substr($range, 1); }else{ $range = explode('-', $range); $c_start = $range[0]; $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end; } $c_end = ($c_end > $this->end) ? $this->end : $c_end; if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) { header('HTTP/1.1 416 Requested Range Not Satisfiable'); header("Content-Range: bytes $this->start-$this->end/$this->size"); exit; } $this->start = $c_start; $this->end = $c_end; $length = $this->end - $this->start + 1; fseek($this->stream, $this->start); header('HTTP/1.1 206 Partial Content'); header("Content-Length: ".$length); header("Content-Range: bytes $this->start-$this->end/".$this->size); } else { header("Content-Length: ".$this->size); } } /** * close curretly opened stream */ private function end() { fclose($this->stream); exit; } /** * perform the streaming of calculated range */ private function stream() { $i = $this->start; set_time_limit(0); while(!feof($this->stream) && $i <= $this->end) { $bytesToRead = $this->buffer; if(($i+$bytesToRead) > $this->end) { $bytesToRead = $this->end - $i + 1; } $data = fread($this->stream, $bytesToRead); echo $data; flush(); $i += $bytesToRead; } } /** * Start streaming video content */ function start() { $this->open(); $this->setHeader(); $this->stream(); $this->end(); } } |
به دلایل زیر این روش به هیچ وجه توصیه نمی شود
- عدم پشتیبانی از فایل های طولانی و حجیم ویدیویی
- عدم پشتیبانی از لایه SSL بر روی HTTP
- نبود امکان کنترل خودکار بر روی فرمت فایل ویدیویی
- عدم حفظ وضعیت قبلی ویدیو
- و …..
همچنین از ابزار قدرمتند FFmpeg نیز برای اینکار می توانید استفاده کنید که البته نیاز به سرور اختصاصی برای نصب و پیکیربندی آن دارید.
برای همین یک روش جایگزین را خدمت شما برای استریم ویدیو در PHP (Video Streaming) معرفی می کنیم.که از کامپونت ReactPHP برای اجرای زنده ویدیو در PHP و پروژه خود استفاده می کنیم.
در بتدا یک اپلیکیشن بسیار ساده Hello world را برای درک نحوه استفاده از ReactPHP و کار با کلاس Server
و مدیریت درخواست های دریافتی ایجاد می کنیم.
منطق اصلی سرور بازگشتی, پاس دادن متد سازنده سرور است. این تابع برگشتی در هربار دریافت یک درخواست (request) جدید اجرا می شود. که خب نمونه شی ساخته شده از Request
را دریافت و آبجکت Response
را بازگشت می دهد.
کلاس سازنده Response
کد پاسخ, هدرها و بدنه اصلی پاسخ را دریافت می کند. در مثال ما, ما در هر درخواست, مقدار ثابت رشته Hello world را برگشت می دهیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php use React\Http\Server; use React\Http\Response; use React\EventLoop\Factory; use Psr\Http\Message\ServerRequestInterface; // init the event loop $loop = Factory::create(); // set up the components $server = new Server(function (ServerRequestInterface $request) { return new Response(200, ['Content-Type' => 'text/plain'], "Hello world\n"); }); $socket = new \React\Socket\Server('127.0.0.1:8000', $loop); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . "\n"; // run the application $loop->run(); |
پس اگر ۱۲۷٫۰٫۰٫۱:۸۰۸۰
را در مرورگر باز کنیم, مقدار Hello World را در نتیجه می بینیم.
مثال ساده استریم ویدیو در PHP
حالا, می توانیم یک مورد جالب را بررسی میکنم. متد سازنده React\Http\Response
می تواند یک نمونه ReadableStreamInterface از ReactPHP را به عنوان بدنه پاسخ (response body) دریافت کند.
یک استیریم قابل خواندن به این منظور استفاده می شود که به جای خواندن کل فایل در مموری, داده ها را از سورس موردنظر بصورت مداوم بخواند. این قابلیت به ما اجازه می دهد که داده ها را مستقیم داخل بنده پاسخ (response body) استریم کند.
برای مثال ما فایل bunny.mp4 را در حالت read باز میکنیم, یک ReadableResourceStream
را با آن ساخته و سپس این استریم را مانند مثال زیر بر بدنه Response
قرار می دیم:
1 2 3 4 5 6 7 |
<?php $server = new Server(function (ServerRequestInterface $request) use ($loop) { $video = new \React\Stream\ReadableResourceStream(fopen('bunny.mp4', 'r'), $loop); return new Response(200, ['Content-Type' => 'video/mp4'], $video); }); |
نکته : در این مثال از fopen()
فقط برای سادگی و نمایش دمو استفاده کردیم! بنابراین برای اپلیکیشن های مختلف خود استفاده کنید زیر با اجرای این فایل سیستم کل درخواست ها مسدود می شود و هر درخواست هم طبیعتا چند ثانیه طول می کشد.
برای ساختن یک نمونه از ReadableResourceStream
نیازه به یک حلقه رویدادی (event loop) داریم. همچنین ما Content-Type
هدر را به video/mp4
تغییر دادیم تا مرورگر را مطلع کنیم که یک ویدیو در حال ارسال است.
نیازی به مشخص کردن هدر Content-Length
نیست چرا که در پشت صحنه ReactPHP بطور خودکار از اینکودینگ chunked استفاده می کند و بطورت مرتب هدر Transfer-Encoding: chunked
استفاده می کند.
حالا مرورگر را رفرش و استریم شدن ویدیو را می بینیم:
خب دیدید به چه راحتی با چند خط کد استریم ویدیو در PHP را پیاده سازی کردیم.
امیدوارم از آموزش استریم ویدیو در PHP نهایت استفاده را برده باشید. به زودی این مقاله ویرایش و قابلیت های جدیدی را برای استریم ویدیو در PHP اضافه می کنیم.
هر سوالی داشتید ، از قسمت نظرات ارسال کنید . سریعا ، پاسخگوی سوالات شما هستیم .
موفق و پیروز باشید
سلام وقت به خیر
من یک سوال خیلی مهم دارم برای خودم و کسایی که میخان وارد حوزه برنامه نویسی بشن و پاسخش از اون مهم تر
کسایی که وارد حوزه برنامه نویسی میشن اندروید سایت یا هر چیز دیگه
و سفارش مثلا طراحی سایت یا اندروید میگیرن مثل اپ فروشگاه اینترنتی
آیا این کد نویسی ها رو از حفظ مینویسن
یعنی قبلش الگو ندارن مثل یک اپ آماده فروشگاهی خارجی یا این که مثل یک اختراع انجام میشه دفترچه راهنماش هست آیا خود گوگل سازنده این زبان این الگوها رو نزاشته که کامل باشه و برنامه نویس ها از روی اون الگو برن جلو
همیشه این سوال ذهنم رو مشغول کرده ایا برنامه نویس خود بدون نیاز به اینها کد مینویسه و آیا حتی بعد مدتها کدهای خودش یادش میمونه؟
سلام ممنون
با تمرین و تکرار زیاد کدها یادتون میمونه و مهم اصول هست یاد بگیرید نه اینکه اول تا اخر کد رو حفظ کنید.
تو مرحله یادگیری اول شما اصول و توابع و نحوه نوشتن کد رو یاد میگیرید و بعد اموزش های پروژه محور که نحوه ساخت مثلا یه اپ یا سایت یا فروشگاه رو یاد میدن میتونید تمام اینارو یاد بگیرید
سلام باتشکر از آموزش خوبتون
گفته شده که از fopen() استفاده نشود. به جای fopen از چه تابعی باید استفاده کنیم؟
سلام
file_put_contents(‘path_and_filename’ , ‘content’ , FILE_APPEND )
تو این حالت ها لینک ویدیو کامل دیده میشه ؟ و راحت میشه لینک دانلود رو در اورد ؟ یا نه
بله لینک دانلود نمایش میده و میشه از درخواست ها استخراجش کرد
با سلام این روش از دانلود کردن توسط idm جلوگیری میکنه ؟
سلام. نه باز امکان دانلود هست
سلام وقتتون بخیر کسی میتونه سایت ویدی وود رو برام آنالیز کنه که کدنویسیش به چه شکل هست.ممنون میشم
سلام استاد یه سوال میشه از اسون ترین روش فیلم بزارید صفر تا صدش
چون متوجه نمیشم
لطفا سمت کاربر رو هم بزرید تا یه پخش زنده کامل داشته باشیم
سلام چجور میشه چیزی رو ساخت که بشه با او بی اس روش استریم کرد؟
سلام. آموزش :
https://obsproject.com/forum/resources/how-to-set-up-your-own-private-rtmp-server-using-nginx.50/
موفق باشید.
استاد سلام چرا من وقتی کد را می نویسم php ارور می دهد
سلام. یا بخاطر ورژن php هست یا اینکه کتابخانه لود نشده که باید ارور رو دید
استاد با سلام مجدد این ارور را می دهد Parse error: syntax error, unexpected ‘use’ (T_USE) بعد آدرس فایل مشکل دار را می دهد
سلام. حتما طبق کامنت قبلی که برای یکی از دوستان شرح دادم reactphp رو هم به پروژه اضافه کنید
با سلام ببخشید چرا هیچ یک از دو روشی که گفتید در لوکال هاست کار نمی کند ؟ و چگونه باید react php را نصب کرد ؟
سلام.
باید پورت موردنظر را بدرستی در لوکال هاست باز کنید.
نیاز نیست کل reactphp رو نصب کنید و فقط اون قسمتی که نیاز هست و داخل آموزش اشاره شده رو با کامپوزر نصب کنید
https://packagist.org/search/?query=reactphp
https://packagist.org/packages/react/stream
https://netparadis.com/what-composer-in-php
ینی میخوام بگم اگه شما سرچ کنی :
آموزش ساخت شیر مرغ در php همه سایت ها در مورد ضرب المثلش میارن… ولی از نت پارادیس نتیجه اصلی میاد …
خوشم میاد مطالبتون تکمیله واقعا ….
دمتون گرم 💪❤️👍
سلام. خوشحالیم که مفید واقع شده.
ممنون از لطفتون.
موفق باشید.
سلام میخام مثل اینستا روی هر ویدویی اسکرول شد پخش بشه
سلام. کافیه autoplay ویدیو رو true بزارید
سلام برادر، خیلی ممنون از آموزش.
من میخوام ویدیو رو به صورت استریم برگردونم ، پکیج رو نصب کردم و عین کد شما زدم ولی روی لوکال هاست اتفاقی نمیافته،!!!
خیلی گیرم، اگر میتونی یه کمکی بم بکن
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) use ($loop) {
$video = new \React\Stream\ReadableResourceStream(fopen(‘1.mp4’, ‘r’), $loop);
return new Response(200, [‘Content-Type’ => ‘video/mp4’], $video);
});
سلام. خوشحالیم که مفید واقع شده. دقیق نمیشه مشکل شما از کجاست. احتمالا یا مشکل از محیط اجرا و ورژن php و یا کدهای شما باشه که تا بررسی نشه نمیشه نظر دقیقی داد.
سلام
من میخوام ویدیویی که از سرورم میاد به پلیرم بصورت تکه های چند ثانیه ای باشه که قابلیت دانلود رو سخت کنه آیا با این راهکار امکانپذیره؟
و سوال دیگه هم اینکه فایل ویدیویی رو تو سرور باز میکنیم،سرعت سایت افت نمیکنه؟اگر ۲۰ تا کاربر همزمان یک ویدیو ۲۰۰ مگابایتی رو پخش کنن سایت میاد پایین
سلام. پایین تر کاربران برسیدند و توضیح داده شده به چه صورت باید انجام بشه. باید یک سرور با پهنای باند بالا و سخت افزار قوی تهیه کنید.
سلام خسته نباشید، میخوایم لینک لایو استریم یک شبکه رو کپی کنم در هوم اسکرین گوشی، ولی هر نیم ساعت ارور forbidden 404 میده وباید مجدد لینک جدید رو کپی کنم، دوستی گفت چون جنریت میشه و امبد کد باید برداری، اما من اصلا بلد نیستم و نمیدونم چطور اینکارو کنم، میشه لطفا مرحله به مرحله بفرمایید چطور باید امبد کد بردارم. ممنون
سلام. ممنون.
از این سایت می توانید برای تولید امبد کد برای ویدیو استفاده کنید :
https://embed.ly/code
موفق باشید.
سلام وقت شما بخیر باشد برای ساخت video chat یا audio chat یا مثلا ساخت پروژه ای مثل video conferece یا audio conference که ما نیاز داریم به طور همزمان تصویر یا صوت را با دوربین یا وبکم یا میکروفون کامپیوتر ضبط نماییم و مستقیم بر روی سرور سایت ارسال کنیم و در همان لحظه هم برای نمایش یا پخش بر روی سایت قرار دهیم در حقیقیت می خواهیم یک پخش زنده آنلاین راه اندازی کنیم لطفا در این مورد راهنمایی بفرمایید که به چه ابزار سخت افزاری و نرم افزاری نیاز داریم و آیا تنها با زبان php این کار انجام شدنی است یا از زبان ها و تکنولوژی های دیگر هم باید استفاده کنیم ؟
با تشکر از شما خدانگهدار شما .
سلام. ممنون.
بله با php امکانش هست و باید یک سرور RTMP داشته باشید. اگر سرور اختصاصی داشته باشید میتونید این فابلیت رو با نصب برنامه مورد نظر روی سرور شخصی پیاده کنید.
اگر سرور شخصی ندارید, یک سری هاستینگ ها هستند که RTMP سرور کانفیگ شده ارایه میدن و میتونید خریداری و ازش استفاده کنید
بعضی اسکریپت هایی هم برای اینکار وجود دارند که از فلش مرورگر استفاده می کنند که باید روی سیستم تمام کسانی که روی این پلتفرم استریم می کنند, این فلش نصب شود که البته این هم جدا از سرور RTMP نیست.
یک سایت هم که RTMP سرور فری تریال میده : https://rtmp-server.com/ که برای تست کارهاتون میتونید ازش استفاده کنید
مورد آخر هم یک ابزار آمده ساخته شده توسط گوگل به اسم WebRTC هست که با جاواسکریپت ساخته شده و این امکان رو در اختیار ما قرار میده که بصورت realtime بتونیم ویدیو استریم کنیم.
با این ابزار دیگه سرور RTMP نیاز نیست ولی به جای آن ابزار دیگری نیاز است روی سرور نصب بشه که در سایت اصلی راهنمایی های لازم اومده
البته ابزارهای جالب دیگری هم هست که فقط از قابلیت websocket در html5 استفاده می کنند که نمونه های آن را در کدکنیون میتونید ببینید که به چه صورت پیاده سازی شدند.
موفق باشید.
تشکر فراوان بابت راهنمایی کامل شما موفق باشید انشاء الله.
سلام
خیلی خوب می شد اگه یاد می دادین چجوری باید چنین چیزی رو بسازیم
سلام این فایل از کجا بگیرم؟
use Evenement\EventEmitter;
مثلاً وبسایت فیلم نت…
البته خودمم بررسی میکنم اسکرپیت های فیلم نت رو بهتون خبر میدم
نمونه های دیگه ای هم هست که با اسنیف ترافیک شبکه فهمیدم…
ولی اینا از قبل فیلم ها رو به چندصد پارت تقسیم میکنن و ذخیره میکنن و روی مرورگر به تدریج لود میشه
سلام … شما همیشه راه حل های جالبی میدید 😀… یک سری سایت هستن خود فایل اصلی فیلم رو به پارت های مجزای ۸ ثانیه ای تبدیل میکنن و داخل اپ تحت وب و یا موبایلی نمایش میدن….
روشی هست که برنامه بالارو تغییر داد و بیاد مثلا ۴۰۰ تا پارت بدون وقفه پشت سر هم پخش کنه؟
سلام ممنونم.
با همچنین موردی تا حالا برنخوردیم و واقعیش تا تست نشه نمیشه گفت که روش قطعی یا نحوه تغییر کد بالا به چه صورت است.
اپ یا نمونه سایت رو معرفی کنید تا بررسی بشه.
موفق باشید.
Please send me your email
netparadis.com@gmail.com
سلام .
عاااالی بود . ممنون <3
سلام . خوشحالم که مفید واقع شده .
موفق باشید.
سلام و عرض خسته نباشید.
میخوام یه اپلیکیشن بسازم که بیاد چندتا فیلم کوتاه رو از یک پوشه در سرور دانلود کنه و پشت سر هم هر کدوم از این فیلم ها رو در اپ به صورت خودکار نمایش بده و بعد از اتمام هر ویدئو به صورت خودکار ویدئوی بعدی رو نمایش بده.ممنون میشم اگه راهنمایی کنید.مرسی.
سلام. ممنون.
در زمینه اپلیکیشن اطلاعات زیادی ندارم که بتونم راهنمایی کنم