|
本帖最后由 gogogo2000 于 2024-7-5 09:43 编辑
程序发布贴: https://www.tvzb.com/thread-3445-1-1.html
关于代理ts流的案例,请看 https://www.tvzb.com/forum.php?m ... 31&fromuid=9158
为了简单说明下聚合程序的使用场景和优点,以下使用 @guoma 大佬发布的看看视频php做案例来演示如何修改php以完全利用livetv来方便的观看直播
说明:
为了保护guoma大佬的劳动成果,以下php中部分代码被替换删除,完整代码请到原贴:https://www.tvzb.com/thread-3347-1-2.html 查看。
php源代码:
- <?php
- error_reporting(0);
- $id = $_GET['id']??'dfws';
- $n = [
- 'dfws' => 1, //东方卫视
- 'shxwzh' => 2, //上海新闻综合
- 'shics' => 3, //上海ics
- 'shds' => 4, //上海都市
- 'dycj' => 5, //第1财 经
- 'jsrw' => 6, //上海纪实人文
- 'hhxd' => 9, //哈哈炫动
- ];
- $date = date('Y-m-d');
- $t = time();
- $nonce = getnonce(8);
- $sign = md5(md5("Api-Version=v1&channel_id={$n[$id]}&date={$date}&nonce={$nonce}&platform=pc×tamp={$t}&version=v2.9.4&28c8edde3d61a0411511d3b1866f0636"));
- $h = [
- "api-version: v1",
- "nonce:$nonce",
- "m-uuid: p8SxKgKBySMALI6mGICre",
- "platform:pc",
- "version:v2.9.4",
- "timestamp:$t",
- "referer: https://live.kankanews.com/",
- "sign:$sign",
- ];
- $json = json_decode(get("https://kapi.kankanews.com/content/pc/tv/programs?channel_id={$n[$id]}&date=".$date,$h)) -> result -> programs;
- for($i=0;$i < count($json);$i++){
- if($json[$i] -> start_time < $t && $t < $json[$i] -> end_time)
- $iid = $json[$i] -> id;
- }
- $sign1 = md5(md5("Api-Version=v1&channel_program_id={$iid}&nonce={$nonce}&platform=pc×tamp={$t}&version=v2.9.4&28c8edde3d61a0411511d3b1866f0636"));
- array_pop($h);
- $h[] = "sign:" .$sign1;
- $encrypted = json_decode(get("https://kapi.kankanews.com/content/pc/tv/program/detail?channel_program_id=".$iid,$h)) -> result -> channel_info -> live_address;
- //RSA公钥
- $public_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 请到原贴查看 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
- $pu_key = openssl_pkey_get_public($public_key);
- $key_len = openssl_pkey_get_details($pu_key)['bits'];
- $decrypted= "";
- $part_len = $key_len / 8;
- $parts = str_split(base64_decode($encrypted), $part_len);
- foreach ($parts as $part) {
- $decrypted_temp = '';
- openssl_public_decrypt($part, $decrypted_temp, $pu_key);
- $decrypted .= $decrypted_temp;
- }
- if($id=='shds'||$id=='hhxd') {
- $playurl = strstr(m3u8($decrypted),'https');
- header('location:'.$playurl);
- //echo $playurl;
- } else {
- $burl = dirname($decrypted).'/';
- $playurl = preg_replace("/(.*?.ts)/i",$burl."$1",m3u8($decrypted));
- header('Content-Type: application/vnd.apple.mpegurl');
- header('location:'.$playurl);
- print_r($playurl);
- }
- function get($url,$header){
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
- curl_setopt($ch, CURLOPT_REFERER, 'https://live.kankanews.com/');
- curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
- $d = curl_exec($ch);
- curl_close($ch);
- return $d;
- }
- function m3u8($url){
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
- curl_setopt($ch, CURLOPT_REFERER, 'https://live.kankanews.com/');
- $d = curl_exec($ch);
- curl_close($ch);
- return $d;
- }
- function getnonce($length) {
- $base36 = base_convert(mt_rand()/mt_getrandmax(), 10, 36);
- return substr($base36, -$length);
- }
- ?>
复制代码 在此脚本中,由于看看对播放列表进行了referer校验,所以返回的m3u8是无法被播放器直接播放的,因此php通过返回一个修改过的m3u8,让最终的播放地址指向了php脚本本身。
脚本再通过仿造header来获得m3u8并推送给播放器。
此php脚本的问题在于每次访问m3u8时,都需要通过看看的api来重新解析一份m3u8,但事实上m3u8存在一个有效期,在有效期内并不需要重新解析。
我们对脚本进行一下修改:
- <?php
- error_reporting(0);
- $id = $_GET['id'] ?? 'dfws';
- $n = [
- 'dfws' => 1, //东方卫视
- 'shxwzh' => 2, //上海新闻综合
- 'shics' => 3, //上海ics
- 'shds' => 4, //上海都市
- 'dycj' => 5, //第1财 经
- 'jsrw' => 6, //上海纪实人文
- 'hhxd' => 9, //哈哈炫动
- ];
- $date = date('Y-m-d');
- $t = time();
- $nonce = getnonce(8);
- $sign = md5(md5("Api-Version=v1&channel_id={$n[$id]}&date={$date}&nonce={$nonce}&platform=pc×tamp={$t}&version=v2.9.4&28c8edde3d61a0411511d3b1866f0636"));
- $h = [
- "api-version: v1",
- "nonce:$nonce",
- "m-uuid: p8SxKgKBySMALI6mGICre",
- "platform:pc",
- "version:v2.9.4",
- "timestamp:$t",
- "referer: https://live.kankanews.com/",
- "sign:$sign",
- ];
- $json = json_decode(get("https://kapi.kankanews.com/content/pc/tv/programs?channel_id={$n[$id]}&date=" . $date, $h))->result->programs;
- for ($i = 0; $i < count($json); $i++) {
- if ($json[$i]->start_time < $t && $t < $json[$i]->end_time)
- $iid = $json[$i]->id;
- }
- $sign1 = md5(md5("Api-Version=v1&channel_program_id={$iid}&nonce={$nonce}&platform=pc×tamp={$t}&version=v2.9.4&28c8edde3d61a0411511d3b1866f0636"));
- array_pop($h);
- $h[] = "sign:" . $sign1;
- $encrypted = json_decode(get("https://kapi.kankanews.com/content/pc/tv/program/detail?channel_program_id=" . $iid, $h))->result->channel_info->live_address;
- //RSA公钥
- $public_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 请到原贴查看 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
- $pu_key = openssl_pkey_get_public($public_key);
- $key_len = openssl_pkey_get_details($pu_key)['bits'];
- $decrypted = "";
- $part_len = $key_len / 8;
- $parts = str_split(base64_decode($encrypted), $part_len);
- foreach ($parts as $part) {
- $decrypted_temp = '';
- openssl_public_decrypt($part, $decrypted_temp, $pu_key);
- $decrypted .= $decrypted_temp;
- }
- // 这里直接通过location返回播放地址即可
- header('location:' . $decrypted);
- // 返回一个json,告诉livetv在访问m3u8时,需要模拟referer
- echo json_encode([
- "headers"=> [
- "Referer" => "https://live.kankanews.com/",
- ]
- ]);
- function get($url, $header)
- {
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
- curl_setopt($ch, CURLOPT_REFERER, 'https://live.kankanews.com/');
- curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
- $d = curl_exec($ch);
- curl_close($ch);
- return $d;
- }
- function m3u8($url)
- {
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
- curl_setopt($ch, CURLOPT_REFERER, 'https://live.kankanews.com/');
- $d = curl_exec($ch);
- curl_close($ch);
- return $d;
- }
- function getnonce($length)
- {
- $base36 = base_convert(mt_rand() / mt_getrandmax(), 10, 36);
- return substr($base36, -$length);
- }
复制代码
在livetv中新建频道,如下:
通过vlc播放生成的地址:
顺利播放
|
|