查看: 29|回复: 3

虎牙不断流

[复制链接]

15

主题

3

回帖

20

积分

新手上路

积分
20
发表于 前天 11:21 | 显示全部楼层 |阅读模式
转贴




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
人生没有彩排,每天都是直播

0

主题

15

回帖

4

积分

新手上路

积分
4
发表于 昨天 18:50 | 显示全部楼层
  1. <?php
  2. /**5合1
  3. * 调用方式:http://yourdomain.com/script.php?hy=11342412
  4. * 支持平台参数:hy(虎牙)、yy(YY)、dyu(斗鱼)、dy(抖音)、bl(B站)
  5. 虎牙周星驰,http://域名/liveplus.php?hy=11342412
  6. 抖cctv6,http://域名/liveplus.php?dy=208823316033
  7. b站,http://域名/liveplus.php?bl=30792542
  8. yy济公,http://域名/liveplus.php?yy=1355265814
  9. 斗鱼庆余年,http://域名/liveplus.php?dyu=7812810
  10. */

  11. error_reporting(0);

  12. function http_request($url, $method = 'GET', $headers = [], $data = null) {
  13.     $ch = curl_init();
  14.     curl_setopt_array($ch, [
  15.         CURLOPT_URL => $url,
  16.         CURLOPT_RETURNTRANSFER => true,
  17.         CURLOPT_FOLLOWLOCATION => true,
  18.         CURLOPT_TIMEOUT => 30,
  19.         CURLOPT_SSL_VERIFYPEER => false,
  20.         CURLOPT_SSL_VERIFYHOST => false,
  21.         CURLOPT_ENCODING => '',
  22.     ]);
  23.     if ($method === 'POST') {
  24.         curl_setopt($ch, CURLOPT_POST, true);
  25.         if ($data !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  26.     }
  27.     if (!empty($headers)) {
  28.         $headerArr = [];
  29.         foreach ($headers as $key => $value) $headerArr[] = "$key: $value";
  30.         curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArr);
  31.     }
  32.     $response = curl_exec($ch);
  33.     $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  34.     curl_close($ch);
  35.     return ['code' => $httpCode, 'body' => $response];
  36. }

  37. function get_headers_only($url, $headers = []) {
  38.     $ch = curl_init($url);
  39.     curl_setopt_array($ch, [
  40.         CURLOPT_RETURNTRANSFER => true,
  41.         CURLOPT_HEADER => true,
  42.         CURLOPT_NOBODY => true,
  43.         CURLOPT_FOLLOWLOCATION => true,
  44.         CURLOPT_TIMEOUT => 10,
  45.         CURLOPT_SSL_VERIFYPEER => false,
  46.         CURLOPT_SSL_VERIFYHOST => false,
  47.     ]);
  48.     if (!empty($headers)) {
  49.         $headerArr = [];
  50.         foreach ($headers as $k => $v) $headerArr[] = "$k: $v";
  51.         curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArr);
  52.     }
  53.     $response = curl_exec($ch);
  54.     $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  55.     $headersStr = substr($response, 0, $headerSize);
  56.     curl_close($ch);
  57.     $headersArr = [];
  58.     $lines = explode("\r\n", $headersStr);
  59.     foreach ($lines as $line) {
  60.         if (strpos($line, ':') !== false) {
  61.             list($key, $value) = explode(':', $line, 2);
  62.             $key = strtolower(trim($key));
  63.             $value = trim($value);
  64.             if (isset($headersArr[$key])) {
  65.                 if (!is_array($headersArr[$key])) $headersArr[$key] = [$headersArr[$key]];
  66.                 $headersArr[$key][] = $value;
  67.             } else {
  68.                 $headersArr[$key] = $value;
  69.             }
  70.         }
  71.     }
  72.     return $headersArr;
  73. }

  74. function cache_get($key) {
  75.     $file = sys_get_temp_dir() . '/' . md5($key) . '.cache';
  76.     if (file_exists($file) && (time() - filemtime($file) < 7 * 24 * 3600)) return file_get_contents($file);
  77.     return null;
  78. }

  79. function cache_set($key, $value) {
  80.     $file = sys_get_temp_dir() . '/' . md5($key) . '.cache';
  81.     file_put_contents($file, $value);
  82. }

  83. const YY_CACHE_DIR = __DIR__ . '/yycache';
  84. const YY_CACHE_TIME = 1800;
  85. const YY_DEFAULT_ID = '34229877';
  86. const YY_QUALITY_LEVEL = 4500;

  87. function yy_getRealUrl($rid, $quality) {
  88.     $cacheFile = YY_CACHE_DIR . "/room_{$rid}_{$quality}.json";
  89.     if (file_exists($cacheFile)) {
  90.         $data = json_decode(file_get_contents($cacheFile), true);
  91.         if (isset($data['time'], $data['url']) && time() - $data['time'] < YY_CACHE_TIME) {
  92.             return $data['url'];
  93.         }
  94.     }

  95.     $apiUrl = "https://interface.yy.com/hls/new/get/{$rid}/{$rid}/{$quality}?source=wapyy&callback=jsonp3";
  96.     $headers = [
  97.         "Referer: https://wap.yy.com/",
  98.         "User-Agent: Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36",
  99.     ];
  100.     $ch = curl_init();
  101.     curl_setopt_array($ch, [
  102.         CURLOPT_URL => $apiUrl,
  103.         CURLOPT_RETURNTRANSFER => true,
  104.         CURLOPT_HTTPHEADER => $headers,
  105.         CURLOPT_SSL_VERIFYPEER => false,
  106.         CURLOPT_SSL_VERIFYHOST => false,
  107.     ]);
  108.     $res = curl_exec($ch);
  109.     curl_close($ch);

  110.     if ($res && preg_match('/jsonp3\((.*)\)/', $res, $matches)) {
  111.         $json = json_decode($matches[1], true);
  112.         if (isset($json['hls']) && !empty($json['hls'])) {
  113.             $realUrl = $json['hls'];
  114.             if (!is_dir(YY_CACHE_DIR)) mkdir(YY_CACHE_DIR, 0755, true);
  115.             file_put_contents($cacheFile, json_encode(['time' => time(), 'url' => $realUrl]));
  116.             return $realUrl;
  117.         }
  118.     }
  119.     return null;
  120. }

  121. function yy_serveM3u8Direct($url) {
  122.     $ch = curl_init();
  123.     curl_setopt_array($ch, [
  124.         CURLOPT_URL => $url,
  125.         CURLOPT_RETURNTRANSFER => true,
  126.         CURLOPT_SSL_VERIFYPEER => false,
  127.         CURLOPT_SSL_VERIFYHOST => false,
  128.         CURLOPT_HTTPHEADER => [
  129.             "Referer: https://wap.yy.com/",
  130.             "User-Agent: Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36"
  131.         ]
  132.     ]);
  133.     $m3u8Content = curl_exec($ch);
  134.     curl_close($ch);

  135.     if (!$m3u8Content) exit;
  136.     $baseUrl = dirname($url) . '/';
  137.     $lines = explode("\n", $m3u8Content);
  138.     header("Content-Type: application/vnd.apple.mpegurl");
  139.     header("Access-Control-Allow-Origin: *");
  140.     header("Cache-Control: no-cache");
  141.     header("Content-Disposition: inline");
  142.     foreach ($lines as $line) {
  143.         $line = trim($line);
  144.         if (empty($line)) continue;
  145.         if ($line[0] === '#') {
  146.             echo $line . "\n";
  147.         } else {
  148.             if (strpos($line, 'http') !== 0) {
  149.                 echo $baseUrl . $line . "\n";
  150.             } else {
  151.                 echo $line . "\n";
  152.             }
  153.         }
  154.     }
  155. }

  156. $handlers = [
  157.     'hy' => function($roomId) {
  158.         $roomId = $roomId ?: '11342412';
  159.         $res = http_request("https://mp.huya.com/cache.php?m=Live&do=profileRoom&roomid={$roomId}", 'GET');
  160.         if ($res['code'] !== 200) return [];
  161.         $data = json_decode($res['body'], true);
  162.         if (!$data || $data['data']['realLiveStatus'] === 'OFF') return [];

  163.         $uid = $data['data']['profileInfo']['uid'];
  164.         $streamName = $data['data']['stream']['baseSteamInfoList'][0]['sStreamName'];
  165.         $multiLine = $data['data']['stream']['flv']['multiLine'];
  166.         $baseUrl = explode('?', $multiLine[array_rand($multiLine)]['url'])[0];

  167.         $seq = (int)$uid + (int)(microtime(true) * 1000);
  168.         $wsTime = dechex(time() + 21600);
  169.         $wsSecret = md5("DWq8BcJ3h6DJt6TY_{$uid}_{$streamName}_" . md5("{$seq}|tars_wap|") . "_{$wsTime}");

  170.         return ['url' => "{$baseUrl}?wsSecret={$wsSecret}&wsTime={$wsTime}&ctype=tars_wap&seqid={$seq}&uid={$uid}&fs=bgct&ver=1"];
  171.     },
  172.     'dyu' => function($roomId) {
  173.         $roomId = $roomId ?: '7812810';
  174.         $did = md5(mt_rand() . microtime(true));
  175.         $k = http_request("https://www.douyu.com/wgapi/livenc/liveweb/websec/getEncryption?did={$did}", 'GET', ['User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Referer' => 'https://www.douyu.com/']);
  176.         if ($k['code'] !== 200) return [];
  177.         $encData = json_decode($k['body'], true)['data'] ?? null;
  178.         if (!$encData) return [];

  179.         $randStr = $encData['rand_str'];
  180.         for ($i = 0; $i < $encData['enc_time']; $i++) $randStr = md5($randStr . $encData['key']);
  181.         $ts = time();
  182.         $auth = md5($randStr . $encData['key'] . $roomId . $ts);
  183.         $postData = "enc_data={$encData['enc_data']}&tt={$ts}&did={$did}&auth={$auth}";

  184.         $res = http_request("https://www.douyu.com/lapi/live/getH5PlayV1/{$roomId}", 'POST', ['Content-Type' => 'application/x-www-form-urlencoded', 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Referer' => "https://www.douyu.com/{$roomId}"], $postData);
  185.         if ($res['code'] !== 200) return [];
  186.         $playData = json_decode($res['body'], true)['data'] ?? null;
  187.         if (!$playData) return [];
  188.         $playUrl = isset($playData['hls_url']) ? $playData['hls_url'] : ($playData['rtmp_url'] . '/' . $playData['rtmp_live']);
  189.         return ['url' => $playUrl];
  190.     },
  191.     'dy' => function($roomId) {
  192.         $rid = trim($roomId) ?: '37917621268';
  193.         $url = "https://live.douyin.com/{$rid}";
  194.         $ttwid = cache_get('douyin_ttwid');
  195.         if (!$ttwid) {
  196.             $responseHeaders = get_headers_only($url, ['User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36']);
  197.             if (isset($responseHeaders['set-cookie'])) {
  198.                 $setCookie = $responseHeaders['set-cookie'];
  199.                 if (is_array($setCookie)) $setCookie = implode('; ', $setCookie);
  200.                 if (preg_match('/ttwid=([^;]+)/', $setCookie, $matches)) {
  201.                     $ttwid = 'ttwid=' . $matches[1];
  202.                     cache_set('douyin_ttwid', $ttwid);
  203.                 } else return [];
  204.             } else return [];
  205.         }

  206.         $headers = ['Cookie' => $ttwid, 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Referer' => 'https://live.douyin.com/'];
  207.         $res = http_request($url, 'GET', $headers);
  208.         if ($res['code'] !== 200) return [];
  209.         $body = $res['body'];

  210.         $flvUrl = null;
  211.         if (preg_match('/\\"origin\\":\\{\\"main\\":\\{\\"flv\\":(.*)tsl/', $body, $flvMatches)) $flvUrl = $flvMatches[1] ?? null;
  212.         if (!$flvUrl && preg_match('/(https?[^"\\\\]*?\.flv[^"\\\\]*)/', $body, $matches)) $flvUrl = $matches[1];

  213.         if ($flvUrl) {
  214.             $segments = explode(',"hls', $flvUrl);
  215.             $firstSegment = $segments[0];
  216.             $cleanedUrl = trim($firstSegment, '"');
  217.             $finalUrl = str_replace(['\u0026', '\\/'], ['&', '/'], $cleanedUrl);
  218.             return ['url' => $finalUrl];
  219.         }
  220.         return [];
  221.     },
  222.     'bl' => function($roomId) {
  223.         $roomId = $roomId ?: '4053897';
  224.         $res = http_request("https://api.live.bilibili.com/room/v1/Room/playUrl?quality=4&cid={$roomId}", 'GET');
  225.         if ($res['code'] !== 200) return [];
  226.         $data = json_decode($res['body'], true);
  227.         if (isset($data['data']['durl'][0]['url'])) return ['url' => $data['data']['durl'][0]['url']];
  228.         return [];
  229.     }
  230. ];

  231. $supported = ['hy', 'yy', 'dyu', 'dy', 'bl'];
  232. foreach ($supported as $param) {
  233.     if (isset($_GET[$param]) && !empty($_GET[$param])) {
  234.         if ($param === 'yy') {
  235.             $rid = preg_replace('/[^0-9]/', '', $_GET['yy']);
  236.             if (empty($rid)) $rid = YY_DEFAULT_ID;
  237.             $quality = isset($_GET['quality']) ? (int)$_GET['quality'] : YY_QUALITY_LEVEL;
  238.             $quality = in_array($quality, [1200,2500,4500,8000]) ? $quality : YY_QUALITY_LEVEL;
  239.             $playUrl = yy_getRealUrl($rid, $quality);
  240.             if (!$playUrl) exit;
  241.             yy_serveM3u8Direct($playUrl);
  242.             exit;
  243.         } else {
  244.             $result = $handlers[$param]($_GET[$param]);
  245.             if (!empty($result) && isset($result['url'])) {
  246.                 header('Location: ' . $result['url']);
  247.                 exit;
  248.             }
  249.             exit;
  250.         }
  251.     }
  252. }
复制代码

评分

参与人数 1金币 +2 收起 理由
admin + 2

查看全部评分

0

主题

15

回帖

4

积分

新手上路

积分
4
发表于 昨天 14:54 | 显示全部楼层
好象只支持国内布置。

2

主题

6

回帖

3

积分

新手上路

积分
3
发表于 3 小时前 | 显示全部楼层

不错,感谢分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

相关侵权、举报、投诉及建议等,请发 E-mail:[email protected]

返回顶部