gogogo2000 发表于 2024-6-28 11:29:20

LiveTV聚合程序使用案例

本帖最后由 gogogo2000 于 2024-7-5 09:43 编辑

程序发布贴: https://www.tvzb.com/thread-3445-1-1.html

关于代理ts流的案例,请看 https://www.tvzb.com/forum.php?mod=redirect&goto=findpost&ptid=3458&pid=159931&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&timestamp={$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&timestamp={$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&timestamp={$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&timestamp={$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播放生成的地址:


顺利播放


hwei 发表于 2024-6-28 11:33:04

点赞点赞,授人以渔

javon 发表于 2024-6-28 11:41:48

可以的,教程

2353027474 发表于 2024-6-28 12:41:21

本帖最后由 2353027474 于 2024-7-2 23:51 编辑

如果是ts呢?比如论坛里的山东地方代理

爆米花0007 发表于 2024-7-5 09:10:46

感谢教学

gogogo2000 发表于 2024-7-5 09:34:14

2353027474 发表于 2024-6-28 12:41
如果是ts呢?比如论坛里的山东地方代理

按照主贴的教学改成直接使用location提供m3u8,并勾选proxy stream即可。
不需要php自己的ts代理功能。

gogogo2000 发表于 2024-7-5 09:42:51

以https://www.tvzb.com/thread-3515-1-1.html 为例,该脚本最后返回的是一个url地址,需要自己去实现ts代理,并且官方的ts存在头部验证,就可以这样改:
原始代码:
echo get_url($id);
修改后的代码:
header("Location: ".get_url($id));
// 返回一个json,告诉livetv在访问m3u8时,需要模拟referer
echo json_encode([
      "headers"=> [
                "Referer" => "https://v.iqilu.com/",
      ]
]);

然后在livetv中添加这个php,解释器选择httpRedirect,并勾选proxy stream。

这样解释器就会跟随这个location跳转,并且代理ts流了
页: [1]
查看完整版本: LiveTV聚合程序使用案例