|
|
- <?php
- $id = isset($_GET['id']) ? $_GET['id'] : 'cctv1';
- get_m3u8_url_and_content($id, $u, $c);
- $c = replace_ts_urls($u, $c);
- echo_content($c);
- function get_channel($id) {
- $n = [
- 'cctv1' => '11200132825562653886',
- 'cctv2' => '12030532124776958103',
- 'cctv4' => '10620168294224708952',
- 'cctv7' => '8516529981177953694',
- 'cctv9' => '7252237247689203957',
- 'cctv10' => '14589146016461298119',
- 'cctv12' => '13180385922471124325',
- 'cctv13' => '16265686808730585228',
- 'cctv17' => '4496917190172866934',
- 'cctv4k' => '2127841942201075403',
- ];
- // 检查频道ID是否存在
- if (isset($n[$id])) {
- $room = $n[$id];
- return $room;
- } else {
- // 返回默认频道ID或空值
- return $n['cctv1'];
- }
- }
- function get_m3u8_url_and_content($id, &$url, &$content)
- {
- $url = load_from_cache($id);
- if ($url) {
- $content = send_request($url, null, null, $code);
- if ($code == 200)
- return true;
- }
- $url = get_m3u8_url_from_web($id);
- if (!$url) {
- $content = '';
- return false;
- }
- $content = send_request($url);
- save_to_cache($id, $url);
- return true;
- }
- function get_m3u8_url_from_web($id) {
- return get_m3u8_url_from_web_core($id);
- }
- function save_to_cache($id, $m3u8_url)
- {
- $a['m3u8_url'] = $m3u8_url;
- array_to_file($a, "cctvnews_cache/$id.txt");
- }
- function load_from_cache($id)
- {
- $cacheFile = "cctvnews_cache/$id.txt";
- $expireSeconds = 60;
- if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $expireSeconds)) {
- file_to_array($cacheFile, $a);
- return $a['m3u8_url'];
- } else {
- return '';
- }
- }
- function file_to_array($filename, &$array) {
- $array = [];
- if (file_exists($filename)) {
- $handle = fopen($filename, 'r');
- if (flock($handle, LOCK_SH)) { // 共享锁,允许其他进程读但禁止写
- $data = file_get_contents($filename);
- $array = unserialize($data);
- flock($handle, LOCK_UN);
- }
- fclose($handle);
- }
- return true;
- }
- function array_to_file($array, $filename) {
- $dir = dirname($filename);
- if (!is_dir($dir) && is_writable(dirname($dir))) {
- if (!@mkdir($dir, 0755, true))
- return false;
- }
- $data = serialize($array);
- file_put_contents($filename, $data, LOCK_EX);
- return true;
- }
- function replace_ts_urls($m3u8_url, $m3u8_content)
- {
- $dest_ts_path = dirname($m3u8_url)."/";
- return preg_replace_callback("/^((?!#).+)$/im",
- function ($matches) use ($dest_ts_path) {
- if (!is_absolute_url($matches[1]))
- $ts = $dest_ts_path.$matches[1];
- else
- $ts = $matches[1];
- return $ts;
- },
- $m3u8_content
- );
- }
- function is_absolute_url($url) {
- return stripos($url, 'http:') === 0 || stripos($url, 'https:') === 0;
- }
- function echo_content($content)
- {
- header("Access-Control-Allow-Origin: *");
- header("Content-Type: application/vnd.apple.mpegurl");
- echo $content;
- }
- function get_m3u8_url_from_web_core($id)
- {
- $room = get_channel($id);
- $url = "https://gateway2.cctvnews.cctv.com/1.0.0/feed/article/live/detail?articleId=$room&scene_type=6";
- $t = round(microtime(true) * 1000);
- $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";
- $es = 'etyEuNdA7GvQU7iPZHqnrBpSFfRyKQTD';
- $sign = base64_encode(hash_hmac('sha256', $er, $es, true));
- $client_id = create_uuid();
- $x_req_ts = $t-1;
- $h = [
- 'accept: application/json',
- 'cookieuid: '.$client_id,
- 'from-client: h5',
- // 'referer: https://m-live.cctvnews.cctv.com/',
- // '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',
- 'userid: '.$client_id,
- 'x-ca-key: 204133710',
- 'x-ca-stage: RELEASE',
- 'x-ca-signature: '.$sign,
- 'x-ca-signature-headers: x-ca-key,x-ca-stage,x-ca-timestamp',
- 'x-ca-timestamp: '.$t,
- 'x-req-ts: '.$x_req_ts,
- 'x-request-id: '.$client_id,
- ];
- $data = send_request($url,$h);
-
- // 添加错误检查
- $json_data = json_decode($data, true);
- if (!$json_data || !isset($json_data['response'])) {
- return '';
- }
-
- $base64_response = $json_data['response'];
- $decoded_response = base64_decode($base64_response);
- if (!$decoded_response) {
- return '';
- }
-
- $response = json_decode($decoded_response, true);
- if (!$response || !isset($response['data'])) {
- return '';
- }
-
- $data = $response['data'];
-
- // 检查嵌套数组键是否存在
- if (isset($data['live_room']) &&
- isset($data['live_room']['liveCameraList']) &&
- !empty($data['live_room']['liveCameraList']) &&
- isset($data['live_room']['liveCameraList'][0]['pullUrlList']) &&
- !empty($data['live_room']['liveCameraList'][0]['pullUrlList']) &&
- isset($data['live_room']['liveCameraList'][0]['pullUrlList'][0]['authResultUrl']) &&
- !empty($data['live_room']['liveCameraList'][0]['pullUrlList'][0]['authResultUrl']) &&
- isset($data['live_room']['liveCameraList'][0]['pullUrlList'][0]['authResultUrl'][0]['authUrl'])) {
-
- $authUrl = $data['live_room']['liveCameraList'][0]['pullUrlList'][0]['authResultUrl'][0]['authUrl'];
- if (stripos($authUrl, 'http') === 0)
- $live = $authUrl;
- else {
- if (isset($data['dk'])) {
- $dk = $data['dk'];
- $live = decrypt($authUrl, $dk, $x_req_ts);
- } else {
- return '';
- }
- }
- $live = str_ireplace('https:', 'http:', $live);
- return $live;
- }
-
- return '';
- }
- function create_uuid() {
- return vsprintf('%04x%04x%04x4%03x%04x%04x%04x%04x', [
- mt_rand(0, 0xffff), mt_rand(0, 0xffff), // 前8位
- mt_rand(0, 0xffff), // 中间4位
- mt_rand(0, 0x0fff), // 第13位固定为4,这里生成后3位
- mt_rand(0, 0x3fff) | 0x8000, // 第17位固定为8/9/a/b(0x8000确保最高位为1000)
- mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) // 最后12位
- ]);
- }
- function send_request($url,$header=null,$post_data=null,&$response_code=null){
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
- curl_setopt($ch, CURLOPT_REFERER, 'https://m-live.cctvnews.cctv.com/');
- curl_setopt($ch, CURLOPT_USERAGENT,
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36');
- if ($header) {
- curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
- }
- if ($post_data) {
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
- }
- $res = curl_exec($ch);
- if (func_num_args() > 3)
- $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
- return $res;
- }
- function decrypt($authUrl, $dk, $x_req_ts) {
- $key = getKey($dk, $x_req_ts);
- $iv = getIv($dk, $x_req_ts);
- return aes_cbc_decrypt($authUrl, $key, $iv);
- }
- function getIv($dk, $x_req_ts) {
- $er = $dk;
- $eo = $x_req_ts;
- $eo = substr($eo, 0, -3);
- return (substr(isset($er) ? $er : '', -8)) . (substr(isset($eo) ? $eo : '', 0, 8));
- }
- function getKey($dk, $x_req_ts) {
- $er = $dk;
- $eo = $x_req_ts;
- $eo = substr($eo, 0, -3);
- return (substr(isset($er) ? $er : '', 0, 8)) . (substr(isset($eo) ? $eo : '', -8));
- }
- function aes_cbc_decrypt($encryptedData, $key, $iv) {
- // Base64解码(若加密数据是Base64编码)
- $encryptedData = base64_decode($encryptedData);
- // 解密操作
- $decrypted = openssl_decrypt(
- $encryptedData,
- 'AES-128-CBC', // 算法模式,可选128/192/256位
- $key,
- OPENSSL_RAW_DATA, // 处理原始数据
- $iv
- );
- return $decrypted;
- }
复制代码
|
|