32 в23цыфв фывфывф
<?php
error_reporting(0);
ini_set('display_errors', 0);
set_time_limit(0);
ini_set('memory_limit', '256M');
// Отдача готового файла
if (isset($_GET['file'])) {
$filePath = __DIR__ . '/videos/' . basename($_GET['file']);
if (!file_exists($filePath)) {
http_response_code(404);
exit('Файл не найден');
}
$fileName = $_GET['name'] ?? 'video.mp4';
$fileSize = filesize($filePath);
header('Content-Type: video/mp4');
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . $fileSize);
header('Accept-Ranges: bytes');
header('Cache-Control: no-cache');
while (ob_get_level()) ob_end_clean();
readfile($filePath);
exit;
}
// Сборка видео
if (isset($_GET['download'])) {
$videoUrl = $_GET['video_url'] ?? '';
$title = $_GET['title'] ?? 'video';
if (!$videoUrl) exit('Нет URL');
$title = preg_replace('/[^\w\s\p{Cyrillic}\-]/ui', '', $title) ?: 'video';
$title = str_replace(['/', '\\', '"', "'", '?', '*', ':', '|', '<', '>'], '', $title);
// Папка videos рядом с downloader.php
$tmpDir = __DIR__ . '/videos/';
if (!is_dir($tmpDir)) mkdir($tmpDir, 0755, true);
// Защита от прямого доступа
if (!file_exists($tmpDir . '.htaccess')) {
file_put_contents($tmpDir . '.htaccess', "Require all denied\n");
}
// Удаляем старые файлы (старше 1 часа)
$oldFiles = glob($tmpDir . '*.mp4');
foreach ($oldFiles as $oldFile) {
if (filemtime($oldFile) < time() - 3600) {
@unlink($oldFile);
@unlink(str_replace('.mp4', '.json', $oldFile));
}
}
$fileHash = md5($videoUrl);
$tmpFile = $tmpDir . $fileHash . '.mp4';
$metaFile = $tmpDir . $fileHash . '.json';
// Если уже собран
if (file_exists($tmpFile) && filesize($tmpFile) > 0) {
echo json_encode([
'success' => true,
'file' => $fileHash . '.mp4',
'name' => $title . '.mp4',
'size' => filesize($tmpFile),
'cached' => true
]);
exit;
}
function getUrl($url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_TIMEOUT => 60,
CURLOPT_CONNECTTIMEOUT => 15,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0',
CURLOPT_TCP_NODELAY => 1,
CURLOPT_BUFFERSIZE => 65536
]);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$m3u8 = getUrl($videoUrl);
if (!$m3u8) exit('Ошибка загрузки');
$lines = explode("\n", $m3u8);
$segments = [];
$base = dirname($videoUrl);
foreach ($lines as $line) {
$line = trim($line);
if ($line && $line[0] !== '#' && (stripos($line, '.ts') !== false || stripos($line, '.mp4') !== false)) {
if (!preg_match('/^https?:\/\//', $line)) $line = rtrim($base, '/') . '/' . ltrim($line, '/');
$segments[] = $line;
}
}
if (empty($segments)) {
for ($i = 0; $i < count($lines); $i++) {
if (strpos($lines[$i], '#EXT-X-STREAM-INF') !== false) {
$next = trim($lines[$i + 1] ?? '');
if ($next && $next[0] !== '#') {
if (!preg_match('/^https?:\/\//', $next)) $next = rtrim($base, '/') . '/' . ltrim($next, '/');
$sub = getUrl($next);
if ($sub) {
$subLines = explode("\n", $sub);
$subBase = dirname($next);
foreach ($subLines as $sl) {
$sl = trim($sl);
if ($sl && $sl[0] !== '#') {
if (!preg_match('/^https?:\/\//', $sl)) $sl = rtrim($subBase, '/') . '/' . ltrim($sl, '/');
$segments[] = $sl;
}
}
}
break;
}
}
}
}
if (empty($segments)) exit('Нет сегментов');
$fp = fopen($tmpFile, 'w+');
if (!$fp) exit('Не удалось создать файл');
foreach ($segments as $segUrl) {
$data = getUrl($segUrl);
if ($data) fwrite($fp, $data);
}
fclose($fp);
if (!file_exists($tmpFile) || filesize($tmpFile) === 0) exit('Не удалось сохранить');
file_put_contents($metaFile, json_encode(['title' => $title, 'created' => time()]));
echo json_encode([
'success' => true,
'file' => $fileHash . '.mp4',
'name' => $title . '.mp4',
'size' => filesize($tmpFile),
'cached' => false
]);
exit;
}
// API
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
$url = $_GET['url'] ?? '';
if (!$url) die(json_encode(['s'=>false,'e'=>'Введите ссылку']));
if (!str_contains($url, 'rutube.ru')) die(json_encode(['s'=>false,'e'=>'Только RuTube']));
preg_match('/video\/([a-f0-9]+)/i', $url, $m);
if (!isset($m[1])) die(json_encode(['s'=>false,'e'=>'Неверная ссылка']));
$id = $m[1];
$ch = curl_init("https://rutube.ru/api/play/options/$id/?no_404=true");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true,CURLOPT_FOLLOWLOCATION=>true,CURLOPT_SSL_VERIFYPEER=>false,CURLOPT_TIMEOUT=>10,CURLOPT_USERAGENT=>'Mozilla/5.0']);
$j = curl_exec($ch); curl_close($ch);
if (!$j) die(json_encode(['s'=>false,'e'=>'API не отвечает']));
$d = json_decode($j, true);
if (!$d||isset($d['detail'])||empty($d['video_balancer']['m3u8'])) die(json_encode(['s'=>false,'e'=>'Видео недоступно']));
$title = $d['title']??'Видео'; $m3u8 = $d['video_balancer']['m3u8'];
$ch2 = curl_init($m3u8);
curl_setopt_array($ch2, [CURLOPT_RETURNTRANSFER=>true,CURLOPT_FOLLOWLOCATION=>true,CURLOPT_SSL_VERIFYPEER=>false,CURLOPT_TIMEOUT=>10,CURLOPT_USERAGENT=>'Mozilla/5.0']);
$mc = curl_exec($ch2); curl_close($ch2);
$lines = explode("\n", $mc); $qualities = []; $base = dirname($m3u8);
for ($i=0;$i<count($lines);$i++) {
if (strpos($lines[$i],'#EXT-X-STREAM-INF')!==false) {
$res='';$bw='';$bwr=0;
if (preg_match('/RESOLUTION=(\d+x\d+)/',$lines[$i],$rm)) $res=$rm[1];
if (preg_match('/BANDWIDTH=(\d+)/',$lines[$i],$bm)){$bwr=(int)$bm[1];$bw=' ('.round($bwr/1000000,1).' Mbps)';}
$nxt=trim($lines[$i+1]??'');
if ($nxt&&$nxt[0]!=='#') {
if (!str_starts_with($nxt,'http')) $nxt=rtrim($base,'/').'/'.ltrim($nxt,'/');
$qualities[($res?:'Поток').$bw]=['url'=>$nxt,'resolution'=>$res,'bandwidth'=>$bwr];
}
}
}
if (empty($qualities)) $qualities['Стандартное']=['url'=>$m3u8,'resolution'=>'','bandwidth'=>0];
echo json_encode(['s'=>true,'d'=>['title'=>$title,'qualities'=>$qualities]],JSON_UNESCAPED_UNICODE);
вфывфывыф фывфывфы
фы
вфы
в
фывф
Цитата
ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва
ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва
ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва
ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва ывавы аыва ыва ываыв ыва
фывфывфвфывфы вфы
фывфывфывфывфывфывфы
фывфывфывфывфывфывфывффы вфыв фыв фв
фывфывфывфвф фвы фы вфы вфывф фвф вф
фывыфвы
фвфывфывфыв фыыфв фвфв