查看: 3|回复: 0

ysxw

[复制链接]

2

主题

0

回帖

8

积分

管理员

积分
8
发表于 昨天 17:09 | 显示全部楼层 |阅读模式
  1. <?php
  2. $id = isset($_GET['id']) ? $_GET['id'] : 'cctv1';
  3. get_m3u8_url_and_content($id, $u, $c);
  4. $c = replace_ts_urls($u, $c);
  5. echo_content($c);



  6. function get_channel($id) {
  7.     $n = [
  8.         'cctv1' => '11200132825562653886',
  9.         'cctv2' => '12030532124776958103',
  10.         'cctv4' => '10620168294224708952',
  11.         'cctv7' => '8516529981177953694',
  12.         'cctv9' => '7252237247689203957',
  13.         'cctv10' => '14589146016461298119',
  14.         'cctv12' => '13180385922471124325',
  15.         'cctv13' => '16265686808730585228',
  16.         'cctv17' => '4496917190172866934',
  17.         'cctv4k' => '2127841942201075403',
  18.     ];
  19.     // 检查频道ID是否存在
  20.     if (isset($n[$id])) {
  21.         $room = $n[$id];
  22.         return $room;
  23.     } else {
  24.         // 返回默认频道ID或空值
  25.         return $n['cctv1'];
  26.     }
  27. }

  28. function get_m3u8_url_and_content($id, &$url, &$content)
  29. {
  30.     $url = load_from_cache($id);
  31.     if ($url) {
  32.         $content = send_request($url, null, null, $code);
  33.         if ($code == 200)
  34.             return true;
  35.     }

  36.     $url = get_m3u8_url_from_web($id);
  37.     if (!$url) {
  38.         $content = '';
  39.         return false;
  40.     }
  41.     $content = send_request($url);

  42.     save_to_cache($id, $url);
  43.     return true;
  44. }

  45. function get_m3u8_url_from_web($id) {
  46.     return get_m3u8_url_from_web_core($id);
  47. }

  48. function save_to_cache($id, $m3u8_url)
  49. {
  50.     $a['m3u8_url'] = $m3u8_url;
  51.     array_to_file($a, "cctvnews_cache/$id.txt");
  52. }

  53. function load_from_cache($id)
  54. {
  55.     $cacheFile = "cctvnews_cache/$id.txt";
  56.     $expireSeconds = 60;
  57.     if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $expireSeconds)) {
  58.         file_to_array($cacheFile, $a);
  59.         return $a['m3u8_url'];
  60.     } else {
  61.         return '';
  62.     }
  63. }

  64. function file_to_array($filename, &$array) {
  65.     $array = [];
  66.     if (file_exists($filename)) {
  67.         $handle = fopen($filename, 'r');
  68.         if (flock($handle, LOCK_SH)) { // 共享锁,允许其他进程读但禁止写
  69.             $data = file_get_contents($filename);
  70.             $array = unserialize($data);
  71.             flock($handle, LOCK_UN);
  72.         }
  73.         fclose($handle);
  74.     }
  75.     return true;
  76. }

  77. function array_to_file($array, $filename) {
  78.     $dir = dirname($filename);
  79.     if (!is_dir($dir) && is_writable(dirname($dir))) {
  80.         if (!@mkdir($dir, 0755, true))
  81.             return false;
  82.     }
  83.     $data = serialize($array);
  84.     file_put_contents($filename, $data, LOCK_EX);
  85.     return true;
  86. }

  87. function replace_ts_urls($m3u8_url, $m3u8_content)
  88. {
  89.     $dest_ts_path = dirname($m3u8_url)."/";
  90.     return preg_replace_callback("/^((?!#).+)$/im",
  91.         function ($matches) use ($dest_ts_path) {
  92.             if (!is_absolute_url($matches[1]))
  93.                 $ts = $dest_ts_path.$matches[1];
  94.             else
  95.                 $ts = $matches[1];
  96.             return $ts;
  97.         },
  98.         $m3u8_content
  99.     );
  100. }

  101. function is_absolute_url($url) {
  102.     return stripos($url, 'http:') === 0 || stripos($url, 'https:') === 0;
  103. }

  104. function echo_content($content)
  105. {
  106.     header("Access-Control-Allow-Origin: *");
  107.     header("Content-Type: application/vnd.apple.mpegurl");
  108.     echo $content;
  109. }



  110. function get_m3u8_url_from_web_core($id)
  111. {
  112.     $room = get_channel($id);
  113.     $url = "https://gateway2.cctvnews.cctv.com/1.0.0/feed/article/live/detail?articleId=$room&scene_type=6";
  114.     $t = round(microtime(true) * 1000);
  115.     $er = "GET\napplication/json\n\n\n\nx-ca-key:204133710\nx-ca-stage:RELEASE\nx-ca-timestamp:$t\n/1.0.0/feed/article/live/detail?articleId=$room&scene_type=6";
  116.     $es = 'etyEuNdA7GvQU7iPZHqnrBpSFfRyKQTD';
  117.     $sign = base64_encode(hash_hmac('sha256', $er, $es, true));
  118.     $client_id = create_uuid();
  119.     $x_req_ts = $t-1;
  120.     $h = [
  121.         'accept: application/json',
  122.         'cookieuid: '.$client_id,
  123.         'from-client: h5',
  124. //        'referer: https://m-live.cctvnews.cctv.com/',
  125. //        'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',
  126.         'userid: '.$client_id,
  127.         'x-ca-key: 204133710',
  128.         'x-ca-stage: RELEASE',
  129.         'x-ca-signature: '.$sign,
  130.         'x-ca-signature-headers: x-ca-key,x-ca-stage,x-ca-timestamp',
  131.         'x-ca-timestamp: '.$t,
  132.         'x-req-ts: '.$x_req_ts,
  133.         'x-request-id: '.$client_id,
  134.     ];
  135.     $data = send_request($url,$h);
  136.    
  137.     // 添加错误检查
  138.     $json_data = json_decode($data, true);
  139.     if (!$json_data || !isset($json_data['response'])) {
  140.         return '';
  141.     }
  142.    
  143.     $base64_response = $json_data['response'];
  144.     $decoded_response = base64_decode($base64_response);
  145.     if (!$decoded_response) {
  146.         return '';
  147.     }
  148.    
  149.     $response = json_decode($decoded_response, true);
  150.     if (!$response || !isset($response['data'])) {
  151.         return '';
  152.     }
  153.    
  154.     $data = $response['data'];
  155.    
  156.     // 检查嵌套数组键是否存在
  157.     if (isset($data['live_room']) &&
  158.         isset($data['live_room']['liveCameraList']) &&
  159.         !empty($data['live_room']['liveCameraList']) &&
  160.         isset($data['live_room']['liveCameraList'][0]['pullUrlList']) &&
  161.         !empty($data['live_room']['liveCameraList'][0]['pullUrlList']) &&
  162.         isset($data['live_room']['liveCameraList'][0]['pullUrlList'][0]['authResultUrl']) &&
  163.         !empty($data['live_room']['liveCameraList'][0]['pullUrlList'][0]['authResultUrl']) &&
  164.         isset($data['live_room']['liveCameraList'][0]['pullUrlList'][0]['authResultUrl'][0]['authUrl'])) {
  165.             
  166.         $authUrl = $data['live_room']['liveCameraList'][0]['pullUrlList'][0]['authResultUrl'][0]['authUrl'];
  167.         if (stripos($authUrl, 'http') === 0)
  168.             $live = $authUrl;
  169.         else {
  170.             if (isset($data['dk'])) {
  171.                 $dk = $data['dk'];
  172.                 $live = decrypt($authUrl, $dk, $x_req_ts);
  173.             } else {
  174.                 return '';
  175.             }
  176.         }
  177.         $live = str_ireplace('https:', 'http:', $live);
  178.         return $live;
  179.     }
  180.    
  181.     return '';
  182. }

  183. function create_uuid() {
  184.     return vsprintf('%04x%04x%04x4%03x%04x%04x%04x%04x', [
  185.         mt_rand(0, 0xffff), mt_rand(0, 0xffff), // 前8位
  186.         mt_rand(0, 0xffff), // 中间4位
  187.         mt_rand(0, 0x0fff), // 第13位固定为4,这里生成后3位
  188.         mt_rand(0, 0x3fff) | 0x8000, // 第17位固定为8/9/a/b(0x8000确保最高位为1000)
  189.         mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) // 最后12位
  190.     ]);
  191. }

  192. function send_request($url,$header=null,$post_data=null,&$response_code=null){
  193.     $ch = curl_init($url);
  194.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  195.     curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  196.     curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  197.     curl_setopt($ch, CURLOPT_REFERER, 'https://m-live.cctvnews.cctv.com/');
  198.     curl_setopt($ch, CURLOPT_USERAGENT,
  199.         'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36');
  200.     if ($header) {
  201.         curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  202.     }
  203.     if ($post_data) {
  204.         curl_setopt($ch, CURLOPT_POST, 1);
  205.         curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
  206.     }
  207.     $res = curl_exec($ch);
  208.     if (func_num_args() > 3)
  209.         $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  210.     curl_close($ch);
  211.     return $res;
  212. }

  213. function decrypt($authUrl, $dk, $x_req_ts) {
  214.     $key = getKey($dk, $x_req_ts);
  215.     $iv = getIv($dk, $x_req_ts);
  216.     return aes_cbc_decrypt($authUrl, $key, $iv);
  217. }

  218. function getIv($dk, $x_req_ts) {
  219.     $er = $dk;
  220.     $eo = $x_req_ts;
  221.     $eo = substr($eo, 0, -3);
  222.     return (substr(isset($er) ? $er : '', -8)) . (substr(isset($eo) ? $eo : '', 0, 8));
  223. }

  224. function getKey($dk, $x_req_ts) {
  225.     $er = $dk;
  226.     $eo = $x_req_ts;
  227.     $eo = substr($eo, 0, -3);
  228.     return (substr(isset($er) ? $er : '', 0, 8)) . (substr(isset($eo) ? $eo : '', -8));
  229. }

  230. function aes_cbc_decrypt($encryptedData, $key, $iv) {
  231.     // Base64解码(若加密数据是Base64编码)
  232.     $encryptedData = base64_decode($encryptedData);

  233.     // 解密操作
  234.     $decrypted = openssl_decrypt(
  235.         $encryptedData,
  236.         'AES-128-CBC',  // 算法模式,可选128/192/256位
  237.         $key,
  238.         OPENSSL_RAW_DATA, // 处理原始数据
  239.         $iv
  240.     );
  241.     return $decrypted;
  242. }
复制代码


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注公众号

相关侵权、举报、投诉及建议等,请发 E-mail:admin@discuz.vip

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖
关注公众号
返回顶部