Реализация Торрент ТВ тут http://torrent-tv.ru/local_ts_proxy.php
Написал скрипт, тут описал процесс как и что происходит, если интересно конечно ...
Ну конечно это будет интересно! Выкладывайте на githab, если хотите чтобы сторонние разработчики подтянулись и внесли свою лепту.
Не нашел github, поэтому выложил сюда ...
Все написано на PHP, старался максимально комментировать - я, вообще, не программист, так на энтузиазме, было просто интересно, так что сильно не пинайте ...
Так что вот, на Ваш суд ...
ace.php:
#!/usr/bin/php
<?phpinclude "./config.php";//соедниение с acestreamengine-client$ace_sock = fsockopen($ace_host, $ace_port, $errno, $errstr, 30);if (!$ace_sock) { echo "$errstr ($errno)<br />\n";} else { //timeout's stream_set_timeout($ace_sock, 5); stream_set_blocking($ace_sock, false); //Рукопожатие с acestreamengine-client $out = "HELLOBG\r\n"; fwrite($ace_sock, $out); while(!feof($ace_sock)) { usleep(80000); //ждем в цикле появления cmd-файла, и в работу его, ежели появился if(file_exists($ace_cmd_file)) { $cmd = file($ace_cmd_file, true); //читаем cmd-файл foreach($cmd as &$_cmd) { print $_cmd . "\r\n"; $hash = explode(' ', $_cmd); $hash = $hash[2]; //останавливаем предыдущий канал fwrite($ace_sock, "STOP\r\n"); //запускаем новый из cmd-файла fwrite($ace_sock, $_cmd . "\r\n"); } //удаляем cmd-файл unlink($ace_cmd_file); } //читаем URL из вывода acestreamengine-client $url = fread($ace_sock, 128); //выдергиваем ... if(preg_match("/START /i", $url)) { $red_url = explode(' ', $url); //log сообщение URL'а от acestreamengine-client echo $red_url[1] . "\r\n"; //открываем соединение к консоли VLC $vlc_sock = fsockopen($vlc_host, $vlc_port, $errno, $errstr, 30); if (!$vlc_sock) { echo "$errstr ($errno)<br />\n"; } else { //timeout's stream_set_timeout($vlc_sock, 5); stream_set_blocking($vlc_sock, false); //вводим password для доступа к VLC fwrite($vlc_sock, $vlc_pass . "\r\n"); //log сообщение в STOUT echo fgets($vlc_sock, 128); usleep(10000); //удаляем все вещание ваапще $vlc_cmd = "del all\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo fgets($vlc_sock, 128); usleep(10000); //организовываем новое $vlc_cmd = "new " . $hash . " broadcast enabled\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo fgets($vlc_sock, 128); usleep(10000); $vlc_cmd = "setup " . $hash . " input " . $red_url[1] . "\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo fgets($vlc_sock, 128); usleep(10000); $vlc_cmd = "setup " . $hash . " output #std{access=http,mux=ts,dst=:" . $vlc_out_port . "/" . $hash . "}\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo fgets($vlc_sock, 128); usleep(10000); $vlc_cmd = "control " . $hash . " play\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo fgets($vlc_sock, 128); fclose($vlc_sock); //Созадем файл, который ждет a.php $f_url = fopen($ace_url_file, "a+"); //пишем в него URL на который будет redirect плеера fwrite($f_url, "http://" . $vlc_out_host . ":" . $vlc_out_port . "/" . $hash); //log сообщение в STOUT echo "http://" . $vlc_out_host . ":" . $vlc_out_port . "/" . $hash; //закрываем файл для a.php fclose($f_url); //chown'им файл для a.php под пользователя, от которого работает веб-сервер, дабы он мог его удалить chown($ace_url_file, $apache_user); } } }}fclose($ace_sock);?>
a.php:
<?php// Берем настройкиinclude "./config.php";// Берем PID канала$id = $_GET['id'];// Создаем врмененный файл для acestreamengine-client-console$f_cmd = fopen($ace_cmd_file, "a+");// Пишем команду для acestreamengine-client-console в файлfwrite($f_cmd, "START PID " . $id . " 0");// Закрываем файлfclose($f_cmd);// Ждем в бесконечном цикле, пока отработает основной скрипт (ace.php) и создаст файл с URL от acestreamengine-client-consolewhile(true) { if($f_url = @fopen($ace_url_file, "r")) { // Читаем URL $url = fread($f_url, 256); // Закрываем файл fclose($ace_url_file); // Удаляем файл unlink($ace_url_file); // Редиректим на URL из файла header("Location: " . $url); // Останваливаем цикл break; } }?>
config.php:
<?php// Пользователь от которого работает http-сервер$apache_user = "www-data";// Пароль для telnet vlc сессии, по default - admin$vlc_pass = "admin";// Хост на котором запущен vlc$vlc_host = "127.0.0.1";// Порт который слушает vlc$vlc_port = "4212";// IP на котором будет выходной поток vlc$vlc_out_host = "192.168.100.2";// Порт на котором будет выходной поток vlc$vlc_out_port = "8903";// Хост на котором запущен acestreamengine-client-console$ace_host = "127.0.0.1";// Порт который слушает acestreamengine-client-console$ace_port = "62062";// Временный файл для передачи параметров acestreamengine-client-console -> daemon (этот скрипт) -> vlc$ace_url_file = "/var/www/tmp/ace.url";// Временный файл для передачи параметров Smart-tv -> http-server (скрипт a.php) -> acestreamengine-client-console$ace_cmd_file = "/var/www/tmp/ace.cmd";//?>
и скрипт запуска stream_tv.sh:
#!/bin/bash
#
case $1 in
start)
echo "Starting VLC ..."
su www-data -c '/usr/bin/vlc-wrapper -d -I telnet --telnet-port 4212 --telnet-password admin'
sleep 5
echo "Starting ACEStreamengine ..."
su www-data -c 'nohup /usr/bin/acestreamengine-client-console & 2> /dev/null'
sleep 5
echo "Starting ACE PHP ..."
su www-data -c 'nohup ./ace.php & 2> /dev/null'
;;
stop)
echo "Stopping ..."
kill `ps ax | grep "acestreamengine" | grep -v "grep" | awk '{print $1}'`
kill `ps ax | grep "start_engine" | grep -v "grep" | awk '{print $1}'`
kill `ps ax | grep "vlc" | grep -v "grep" | awk '{print $1}'`
kill `ps ax | grep "ace.php" | grep -v "grep" | awk '{print $1}'`
;;
*)
echo " * Usage: ./stream_tv.sh {start|stop}"
esac
P.S.
Соответственно, для пользователя $apache_user, в моем случае это www-data - нужен валидный shell, правильнее было бы завести нового пользователя и запускать все от него ...
P.S.2.
HTTP-запрос должен быть, в моем случае, следующего вида: http://192.168.100.2:8903/a.php?id=<PID>
На работе делать было нечего, дело было к вечеру ...
Допилил свой скрипт до 1-го файла, также теперь на каждый запрос - свой поток, т.е. можно смотреть на нескольких клиентах (в прошлом варианте - только один мог).
Надеюсь Модератор меня не грохнет, за то что я сюда прямо source code запихиваю ...
Вот:
a.php:
<?phpset_time_limit(0);ignore_user_abort(true);ob_start();include "./config.php";$hash = $_GET[id];//соедниение с acestreamengine-client$ace_sock = fsockopen($ace_host, $ace_port, $errno, $errstr, 30);if (!$ace_sock) { echo "$errstr ($errno)<br />\n";} else { //timeout's stream_set_timeout($ace_sock, 5); stream_set_blocking($ace_sock, false); //Рукопожатие с acestreamengine-client $out = "HELLOBG\r\n"; fwrite($ace_sock, $out); while(!feof($ace_sock)) { usleep(80000); // Если этот этап уже проходил - он не нужен ... пропускаем ... if(!$s) { fwrite($ace_sock, "START PID " . $hash . " 0\r\n"); $s = true; } //читаем URL из вывода acestreamengine-client $url = fread($ace_sock, 128); //выдергиваем ... if(preg_match("/START http/i", $url)) { $ace_url = explode(' ', $url); $ace_url = $ace_url[1]; //log сообщение URL'а от acestreamengine-client echo $ace_url . "\r\n"; //открываем соединение к консоли VLC, и проверяем не открывали ли мы его ранее ... if(!$vlc_s) { $vlc_s = true; $vlc_sock = fsockopen($vlc_host, $vlc_port, $errno, $errstr, 30); if (!$vlc_sock) { echo "$errstr ($errno)<br />\n"; } else { //timeout's stream_set_timeout($vlc_sock, 5); stream_set_blocking($vlc_sock, false); //вводим password для доступа к VLC fwrite($vlc_sock, $vlc_pass . "\r\n"); //log сообщение в STOUT usleep(10000); echo fgets($vlc_sock, 128) . "\r\n"; usleep(10000); // Определяем порт для VLC $start_port = explode("-", $vlc_out_ports); $end_port = $start_port[1]; $start_port = $start_port[0]; $vlc_out_port = rand($start_port, $end_port); //организовываем streaming } if($ace_url) { $vlc_name_stream = $hash . "-" . md5($vlc_out_port); $vlc_cmd = "new " . $vlc_name_stream . " broadcast enabled\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo $vlc_cmd . "\r\n"; echo fgets($vlc_sock, 128) . "\r\n"; usleep(10000); $vlc_cmd = "setup " . $vlc_name_stream . " input " . $ace_url . "\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo $vlc_cmd . "\r\n"; echo fgets($vlc_sock, 128) . "\r\n"; usleep(10000); $vlc_cmd = "setup " . $vlc_name_stream . " output #std{access=http,mux=ts,dst=:" . $vlc_out_port . "/" . $vlc_name_stream . "}\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo $vlc_cmd . "\r\n"; echo fgets($vlc_sock, 128) . "\r\n"; usleep(10000); $vlc_cmd = "control " . $vlc_name_stream . " play\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo $vlc_cmd . "\r\n"; echo fgets($vlc_sock, 128) . "\r\n"; // Формируем URL $vlc_out_url = "http://" . $vlc_out_host . ":" . $vlc_out_port . "/" . $vlc_name_stream; // Редиректим на URL полученный от VLC header("Location: " . $vlc_out_url); // Говорим плееру, что закончили, но продолжаем выполнение скрипта ... $length = ob_get_length(); header("Connection: close"); header("Content-Length: " . $length); header("Content-Encoding: none"); header("Accept-Ranges: bytes"); ob_end_flush(); ob_flush(); flush(); //log сообщение в STOUT echo $vlc_out_url . "\r\n"; } } // Проверяем не отключился ли клиент, если отключился - закрываем трансяции и сидирование (что плохо, но канала на все каналы не хватит ... =( ). while(true) { sleep(60); if(!exec('lsof -i tcp:' . $vlc_out_port . ' | grep "ESTABLISHED"')) { fwrite($ace_sock, "STOP\r\n"); fwrite($ace_sock, "SHUTDOWN\r\n"); fclose($ace_sock); fwrite($vlc_sock, "del " . $vlc_name_stream . "\r\n"); fwrite($vlc_sock, "quit\r\n"); fclose($vlc_sock); exit(0); } } } } }?>
config.php:
<?php// Пользователь от которого работает http-сервер$apache_user = "www-data";// Пароль для telnet vlc сессии$vlc_pass = "admin";// Хост на котором запущен vlc$vlc_host = "127.0.0.1";// Порт который слушает vlc$vlc_port = "4212";// IP на котором будет выходной поток vlc$vlc_out_host = "192.168.100.2";// Диапазон портов VLC$vlc_out_ports = "10000-20000";// Хост на котором запущен acestreamengine-client-console$ace_host = "127.0.0.1";// Порт который слушает acestreamengine-client-console$ace_port = "62062";// Временный файл для передачи параметров acestreamengine-client-console -> daemon (этот скрипт) -> vlc$ace_url_file = "/var/www/tmp/ace.url";// Временный файл для передачи параметров Smart-tv -> http-server (скрипт a.php) -> acestreamengine-client-console$ace_cmd_file = "/var/www/tmp/ace.cmd";?>
Да, и теперь используется диапазон портов, на которые происходит редирект ...
Жду осуждений, обсуждений и вопросов =)
Всем спасибо за внимание ...
Moderators - Sorry ...
допилена версия в 1 скрипт и файл с параметрами, запускает трансляцию при запросе, при отсутствии подключенных клиентов в течение минуты останавливает трансляцию, также проверяет на предмет существующей трансляции и если таковая имеется - соответственно редирект на нее.:
a.php:
<?phpinclude "./config.php";$hash = $_GET[id];// Проверяем существует ли файл трансляции, если да - то сразу редиректим на URL из файла и заканчиваем работу if(file_exists($dir . "/" . $hash)) { $fstream = fopen($dir . "/" . $hash, "r"); $contents = fread($fstream, filesize($dir . "/" . $hash)); echo "Translation exist: " . $contents . "\r\n"; echo "Redirecting ...\r\n"; fclose($fstream); header("Location: " . $contents); exit(0); }//limits ...set_time_limit(0);ignore_user_abort(true);ob_start();//соедниение с acestreamengine-client$ace_sock = fsockopen($ace_host, $ace_port, $errno, $errstr, 30);if (!$ace_sock) { echo "$errstr ($errno)<br />\n";} else { //timeout's stream_set_timeout($ace_sock, 5); stream_set_blocking($ace_sock, false); //Рукопожатие с acestreamengine-client $out = "HELLOBG\r\n"; fwrite($ace_sock, $out); while(!feof($ace_sock)) { usleep(80000); // Если этот этап уже проходил - он не нужен ... пропускаем ... if(!$s) { fwrite($ace_sock, "START PID " . $hash . " 0\r\n"); $s = true; } //читаем URL из вывода acestreamengine-client $url = fread($ace_sock, 128); //выдергиваем ... if(preg_match("/START http/i", $url)) { $ace_url = explode(' ', $url); $ace_url = $ace_url[1]; //log сообщение URL'а от acestreamengine-client echo $ace_url . "\r\n"; //открываем соединение к консоли VLC, и проверяем не открывали ли мы его ранее ... if(!$vlc_s) { $vlc_s = true; $vlc_sock = fsockopen($vlc_host, $vlc_port, $errno, $errstr, 30); if (!$vlc_sock) { echo "$errstr ($errno)<br />\n"; } else { //timeout's stream_set_timeout($vlc_sock, 5); stream_set_blocking($vlc_sock, false); //вводим password для доступа к VLC fwrite($vlc_sock, $vlc_pass . "\r\n"); //log сообщение в STOUT usleep(10000); echo fgets($vlc_sock, 128) . "\r\n"; usleep(10000); // Определяем порт для VLC $start_port = explode("-", $vlc_out_ports); $end_port = $start_port[1]; $start_port = $start_port[0]; $vlc_out_port = rand($start_port, $end_port); //организовываем streaming } if($ace_url) { $vlc_name_stream = $hash . "-" . md5($vlc_out_port); $vlc_cmd = "new " . $vlc_name_stream . " broadcast enabled\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo $vlc_cmd . "\r\n"; echo fgets($vlc_sock, 128) . "\r\n"; usleep(10000); $vlc_cmd = "setup " . $vlc_name_stream . " input " . $ace_url . "\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo $vlc_cmd . "\r\n"; echo fgets($vlc_sock, 128) . "\r\n"; usleep(10000); $vlc_cmd = "setup " . $vlc_name_stream . " output #std{access=http,mux=ts,dst=:" . $vlc_out_port . "/" . $vlc_name_stream . "}\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo $vlc_cmd . "\r\n"; echo fgets($vlc_sock, 128) . "\r\n"; usleep(10000); $vlc_cmd = "control " . $vlc_name_stream . " play\r\n"; fwrite($vlc_sock, $vlc_cmd); //log сообщение в STOUT echo $vlc_cmd . "\r\n"; echo fgets($vlc_sock, 128) . "\r\n"; // Формируем URL $vlc_out_url = "http://" . $vlc_out_host . ":" . $vlc_out_port . "/" . $vlc_name_stream; // Редиректим на URL полученный от VLC header("Location: " . $vlc_out_url); // Говорим плееру, что закончили, но продолжаем выполнение скрипта ... $length = ob_get_length(); header("Connection: close"); header("Content-Length: " . $length); header("Content-Encoding: none"); header("Accept-Ranges: bytes"); ob_end_flush(); ob_flush(); flush(); //log сообщение в STOUT echo $vlc_out_url . "\r\n"; echo "http://" . $vlc_out_host . ":" . $vlc_out_port . "/" . $hash . "\r\n"; // Создаем файл трансляции, вдруг кто еще захочет смотреть именно этот канал echo "Translation doesn't exist... Creating ... \r\n"; $f_url = fopen($dir . "/" . $hash, "a+"); fwrite($f_url, $vlc_out_url); fclose($f_url); } } // Проверяем не отключился ли клиент, если отключился - закрываем трансяции и сидирование (что плохо, но канала на все каналы не хватит ... =( ). while(true) { sleep(60); if(!exec('lsof -i tcp:' . $vlc_out_port . ' | grep "ESTABLISHED"')) { fwrite($ace_sock, "STOP\r\n"); fwrite($ace_sock, "SHUTDOWN\r\n"); fclose($ace_sock); echo "Stopping VLC " . $hash . "\r\n"; fwrite($vlc_sock, "del " . $vlc_name_stream . "\r\n"); fwrite($vlc_sock, "quit\r\n"); fclose($vlc_sock); echo "Deleting file " . $dir . "/" . $hash . "\r\n"; unlink($dir . "/" . $hash); exit(0); } } } } }?>
config.php:
<?php// Пользователь от которого работает http-сервер$apache_user = "www-data";// Пароль для telnet vlc сессии$vlc_pass = "admin";// Хост на котором запущен vlc$vlc_host = "127.0.0.1";// Порт который слушает vlc$vlc_port = "4212";// IP на котором будет выходной поток vlc$vlc_out_host = "192.168.100.2";// Диапазон портов VLC$vlc_out_ports = "10000-20000";// Хост на котором запущен acestreamengine-client-console$ace_host = "127.0.0.1";// Порт который слушает acestreamengine-client-console$ace_port = "62062";// Временный файл для передачи параметров acestreamengine-client-console -> daemon (этот скрипт) -> vlc$ace_url_file = "/var/www/tmp/ace.url";// Временный файл для передачи параметров Smart-tv -> http-server (скрипт a.php) -> acestreamengine-client-console$ace_cmd_file = "/var/www/tmp/ace.cmd";// Директория для файлов трансляций$dir = "./streams";?>
скрипт запуска VLC и acestreamengine:
stream_tv.sh:
#!/bin/bash
#
case $1 in
start)
echo "Starting VLC ..."
su www-data -c '/usr/bin/vlc-wrapper -d -I telnet --telnet-port 4212 --telnet-password infinity'
sleep 1
echo "Starting ACEStreamengine ..."
su www-data -c 'nohup /usr/bin/acestreamengine-client-console & 2> /dev/null'
;;
stop)
echo "Stopping ..."
kill `ps ax | grep "acestreamengine" | grep -v "grep" | awk '{print $1}'`
kill `ps ax | grep "start_engine" | grep -v "grep" | awk '{print $1}'`
kill `ps ax | grep "vlc" | grep -v "grep" | awk '{print $1}'`
;;
*)
echo " * Usage: ./stream_tv.sh {start|stop}"
esac
нужно создать каталог $dir (в нем будут храниться файлы трансляций с URL трансляций внутри), соответственно дать права на него пользователю, от которого работает web-сервер.