mirror of
https://github.com/ihmily/DouyinLiveRecorder.git
synced 2025-12-26 05:48:32 +08:00
Add fetch douyin live stream url API
This commit is contained in:
parent
549c478b75
commit
3aae5014b3
118
api/convert.php
Normal file
118
api/convert.php
Normal file
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Author: Hmily
|
||||
* Github:https://github.com/ihmily
|
||||
* Date: 2023-07-20 21:06:20
|
||||
* Copyright (c) 2023 by Hmily, All Rights Reserved.
|
||||
* Function:convert short url to long url
|
||||
* Address:https://github.com/ihmily/DouyinLiveRecorder
|
||||
*/
|
||||
|
||||
|
||||
// 该代码主要是用来转换地址,将短app端直播分享链接转为PC网页端长链接
|
||||
header('Content-type: application/json; charset=utf-8');
|
||||
|
||||
|
||||
if(empty($_GET['url'])){
|
||||
exit(json_encode(['code'=>-2,'msg'=>'请输入app端直播间分享地址'],448));
|
||||
}
|
||||
$share_url=$_GET['url'];
|
||||
|
||||
$get_id=get_redirect_url($share_url);
|
||||
preg_match('/reflow\/(.*?)\?u_code/', $get_id, $room_id);
|
||||
preg_match('/&sec_user_id=(.*?)&ecom_share_track_params/', $get_id, $sec_user_id);
|
||||
$room_data=get_live_web_rid($room_id[1],$sec_user_id[1]);
|
||||
$title=$room_data[0];
|
||||
$web_rid=$room_data[1];
|
||||
|
||||
|
||||
if(empty($web_rid)){
|
||||
exit(json_encode(['code'=>-1,'status'=>'解析失败','msg'=>'请检测链接是否正确,多次失败请联系作者修复!https://github.com/ihmily/DouyinLiveRecorder'],448));
|
||||
}
|
||||
$long_url="https://live.douyin.com/".$web_rid;
|
||||
$return=
|
||||
[
|
||||
'code'=>0,
|
||||
'status'=>'解析成功',
|
||||
'title'=>$title,
|
||||
'room_id'=>$room_id[1],
|
||||
'share_url'=>$share_url,
|
||||
'long_url'=>$long_url,
|
||||
'source'=>'源码地址:https://github.com/ihmily/DouyinLiveRecorder'
|
||||
];
|
||||
exit(json_encode($return,448));
|
||||
|
||||
|
||||
// 抖音X-bogus算法,这里我直接封装成接口进行调用了
|
||||
function get_xbogus($url) {
|
||||
$query = parse_url($url, PHP_URL_QUERY);
|
||||
$url = "http://43.138.133.177:8890/xbogus";
|
||||
$data = array(
|
||||
'url' => $query,
|
||||
'ua' => "Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-G973U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/14.2 Chrome/87.0.4280.141 Mobile Safari/537.36",
|
||||
);
|
||||
$params = http_build_query($data);
|
||||
$url = $url . '?' . $params;
|
||||
$response = file_get_contents($url);
|
||||
$response_json = json_decode($response, true);
|
||||
$xbogus = $response_json['result'];
|
||||
// echo "生成的X-Bogus签名为: " . $xbogus;
|
||||
return $xbogus;
|
||||
}
|
||||
|
||||
|
||||
function get_live_web_rid($room_id, $sec_user_id) {
|
||||
|
||||
$url = 'https://webcast.amemv.com/webcast/room/reflow/info/?verifyFp=verify_lk07kv74_QZYCUApD_xhiB_405x_Ax51_GYO9bUIyZQVf&type_id=0&live_id=1&room_id='.$room_id.'&sec_user_id='.$sec_user_id.'&app_id=1128&msToken=wrqzbEaTlsxt52-vxyZo_mIoL0RjNi1ZdDe7gzEGMUTVh_HvmbLLkQrA_1HKVOa2C6gkxb6IiY6TY2z8enAkPEwGq--gM-me3Yudck2ailla5Q4osnYIHxd9dI4WtQ==';
|
||||
$xbogus = get_xbogus($url); // 获取X-Bogus算法
|
||||
|
||||
$url = $url . "&X-Bogus=" . $xbogus;
|
||||
$headers = array(
|
||||
'User-Agent: Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-G973U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/14.2 Chrome/87.0.4280.141 Mobile Safari/537.36',
|
||||
'Accept:application/json, text/plain, */*',
|
||||
'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
|
||||
);
|
||||
$cookies='s_v_web_id=verify_lk07kv74_QZYCUApD_xhiB_405x_Ax51_GYO9bUIyZQVf';
|
||||
$json_data = get_curl($url,$headers,$cookies);
|
||||
$json_data = json_decode($json_data, true);
|
||||
$web_rid = $json_data['data']['room']['owner']['web_rid'];
|
||||
$title=$json_data["data"]['room']['title'];
|
||||
return [$title,$web_rid];
|
||||
}
|
||||
|
||||
|
||||
// 封装的CURL函数
|
||||
function get_curl($url,$headers=array(),$cookies=''){
|
||||
$curl=curl_init((string)$url);
|
||||
curl_setopt($curl,CURLOPT_HEADER,false);
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
|
||||
curl_setopt($curl, CURLOPT_ENCODING, "");
|
||||
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
|
||||
curl_setopt($curl,CURLOPT_HTTPHEADER,$headers);
|
||||
curl_setopt($curl, CURLOPT_COOKIE, $cookies);
|
||||
curl_setopt($curl,CURLOPT_TIMEOUT,20);
|
||||
$data = curl_exec($curl);
|
||||
// var_dump($data);
|
||||
curl_close($curl);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
function get_redirect_url($url) {
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, array( "User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"));
|
||||
curl_setopt($curl, CURLOPT_HEADER, true);
|
||||
curl_setopt($curl, CURLOPT_NOBODY, 1);
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl,CURLOPT_TIMEOUT,20);
|
||||
$ret = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
preg_match("/Location: (.*?)\r\n/iU",$ret,$location);
|
||||
return $location[1];
|
||||
}
|
||||
132
api/index.php
Normal file
132
api/index.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Author: Hmily
|
||||
* Github:https://github.com/ihmily
|
||||
* Date: 2023-07-20 21:06:20
|
||||
* Copyright (c) 2023 by Hmily, All Rights Reserved.
|
||||
* Function:Spider about the stream url of douyin live
|
||||
* Address:https://github.com/ihmily/DouyinLiveRecorder
|
||||
*/
|
||||
|
||||
header('Content-type: application/json; charset=utf-8');
|
||||
|
||||
if(empty($_GET['url'])){
|
||||
exit(json_encode(['code'=>-2,'msg'=>'请输入抖音直播间地址'],448));
|
||||
}
|
||||
$live_url=$_GET['url'];
|
||||
$pattern = "/^https:\/\/v\.douyin\.com\/\w+\/$/";
|
||||
if (preg_match($pattern, $live_url)) {
|
||||
// 判断是否是app端分享链接,如果是则转为PC网页端地址,否则无法解析
|
||||
// 示例链接:
|
||||
// $live_url="https://live.douyin.com/187615265444";
|
||||
$json_str=get_curl("https://hmily.vip/api/dy/live/convert.php?url=".$live_url);
|
||||
$json_data=json_decode($json_str,true);
|
||||
$live_url = $json_data['long_url'];
|
||||
}
|
||||
|
||||
$json_data2=get_json_data($live_url);
|
||||
$return=get_stream_url2($json_data2,$live_url); // 选用第二种方式
|
||||
exit(json_encode($return,448));
|
||||
|
||||
|
||||
function get_json_data($url) {
|
||||
$headers = array(
|
||||
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
|
||||
'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
|
||||
'Referer: https://live.douyin.com/',
|
||||
);
|
||||
|
||||
$cookies='ttwid=1%7CIkooT8SJQrpeYtHlSALuhz9BdcHpaaf9tHQRKHuDaYE%7C1687785070%7C6690250483b63b6482128174d0f93bd879614d76f1b6e03ca52e032cf7fbaafd; passport_csrf_token=52bece134ac246c81163cc93b72f86a6; passport_csrf_token_default=52bece134ac246c81163cc93b72f86a6; d_ticket=2b9e3eb3626216c0122f0d980f867deb7b414; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; passport_auth_status=a74f300f376940d65914eb148d55ca96%2C9ca487aea255972120d502f736c5dd7b; passport_auth_status_ss=a74f300f376940d65914eb148d55ca96%2C9ca487aea255972120d502f736c5dd7b; sso_auth_status=52ecac30d95890cc7896c880366aa21a; sso_auth_status_ss=52ecac30d95890cc7896c880366aa21a; LOGIN_STATUS=1; store-region=cn-fj; store-region-src=uid; __security_server_data_status=1; __live_version__=%221.1.1.1853%22; live_can_add_dy_2_desktop=%220%22; xgplayer_user_id=528819598596; msToken=ZfXzPPa_KqQDF9wkHigKqgyUMIt33-qgLl1qqthGsAea4L69i9wxWaGH4GaQ9M_Q-eqhLpnD4v8FRGIj9KGJGIyLmjPkR1uepZ0gBaqhCkqK1KaauPXT_VK_uVgW6q4=; home_can_add_dy_2_desktop=%220%22; strategyABtestKey=%221689685952.92%22; FOLLOW_LIVE_POINT_INFO=%22MS4wLjABAAAAf6aekfyBsc4u8jMkeYbgnkFa0ksIWKWpGOywuyHXyo4%2F1689609600000%2F0%2F1689606316434%2F0%22; FOLLOW_NUMBER_YELLOW_POINT_INFO=%22MS4wLjABAAAAf6aekfyBsc4u8jMkeYbgnkFa0ksIWKWpGOywuyHXyo4%2F1689609600000%2F0%2F0%2F1689594083273%22; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Atrue%2C%22volume%22%3A0.6%7D; device_web_cpu_core=8; device_web_memory_size=-1; webcast_local_quality=origin; csrf_session_id=0446f50cc7e08f146ad07351af90f413; __ac_nonce=064be522600a12daa29ff; __ac_signature=_02B4Z6wo00f0145FB4AAAIDCkga5P5okFMuOdAMAAIc3h1Lmbu.WZmNdgawlJBkHRSAf1yndkZFgF.zN2OHlE62.f.4ZFt740eSkTrQW8j3EM2s9s3vtK9LGh-h9jhUkgSbj4UOtYTqpCZZc88; webcast_leading_last_show_time=1690194481638; webcast_leading_total_show_times=1; odin_tt=6ebbe0a3c1b4e5bc6d333c5c7514fc88a288b3b03b1f0cf34826dee5d6d6394620f17fd4eb624b710954233f38fa3c67fd4a5338bffaa792a2cf71d1b51d837f079925497d6b372f47a577d779036a71; msToken=uHqyINCG79-ojuC5cXU6tYm0Av3BqNzqLkFGvbNw5QmSCtFY7xYHJjJ3wu-gk2Evj5QQ7D6UMsz2inlRN-aZf8xTGMAnpmgieOrygPqoK7QboFwCXR7aLi4KKcFXvFu2; tt_scid=BVvDLf3XEG4PZlY2-haad4.kR2BYWdq4X88b6-sPA2Wpg2lsSDI5M7YuZ7H-GPf.6646';
|
||||
|
||||
$html_str = get_curl($url,$headers,$cookies);
|
||||
preg_match('/<script id="RENDER_DATA" type="application\/json">(.*?)<\/script><script type=/', $html_str, $matches);
|
||||
$quote_json_str = $matches[1];
|
||||
$unquote_json_str = urldecode($quote_json_str);
|
||||
$json_data = json_decode($unquote_json_str, true);
|
||||
return $json_data;
|
||||
}
|
||||
|
||||
|
||||
# 第一种数据
|
||||
function get_stream_url($json_data) {
|
||||
$initialState = $json_data['app']['initialState'];
|
||||
$streamStore = $initialState['streamStore'];
|
||||
$roomStore = $initialState['roomStore'];
|
||||
$is_login = $json_data['app']['odin']['user_is_login'];
|
||||
$streamData = $streamStore['streamData']['H265_streamData']['options'];
|
||||
$stream = $streamStore['streamData']['H265_streamData']['stream'];
|
||||
$stream2 = $streamStore['streamData']['H264_streamData']['stream'];
|
||||
$anchor_name = $roomStore['roomInfo']['anchor']['nickname'];
|
||||
$data=array();
|
||||
if ($stream === null) {
|
||||
$data=["live_status"=>'主播未开播或者直播已经结束!'];
|
||||
} else {
|
||||
|
||||
$m3u8_url = $stream['origin']['main']['hls'];
|
||||
$m3u8_url2 = $stream2['origin']['main']['hls'];
|
||||
$data=["title"=>$live_title,'stream'=>['m3u8_url_265'=>$m3u8_url,'m3u8_url_264'=>$m3u8_url2]];
|
||||
}
|
||||
$return=[
|
||||
'code'=>0,
|
||||
'status'=>'解析成功',
|
||||
'anchor_name'=>$anchor_name,
|
||||
'live_url'=>$live_url,
|
||||
'data'=>$data,
|
||||
'source'=>'源码地址:https://github.com/ihmily/DouyinLiveRecorder'
|
||||
];
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
# 第二种数据(更好)
|
||||
function get_stream_url2($json_data,$live_url) {
|
||||
$roomStore = $json_data['app']['initialState']['roomStore'];
|
||||
$roomInfo = $roomStore['roomInfo'];
|
||||
$anchor_name = $roomInfo['anchor']['nickname'];
|
||||
$live_title = $roomInfo['room']['title'] ;
|
||||
// 获取直播间状态
|
||||
$status = $roomInfo["room"]["status"]; // 直播状态2是正在直播.4是未开播
|
||||
$data=array();
|
||||
if ($status == 4) {
|
||||
$data=["live_status"=>'主播未开播或者直播已经结束!'];
|
||||
} else {
|
||||
$is_login = $json_data['app']['odin']['user_is_login'];
|
||||
$stream_url = $roomInfo['room']['stream_url'];
|
||||
// flv视频流链接
|
||||
$flv_url_list = $stream_url['flv_pull_url'];
|
||||
// m3u8视频流链接
|
||||
$m3u8_url_list = $stream_url['hls_pull_url_map'];
|
||||
$data=["title"=>$live_title,'stream'=>['flv_url_list'=>$flv_url_list,'m3u8_url_list'=>$m3u8_url_list]];
|
||||
|
||||
}
|
||||
$return=[
|
||||
'code'=>0,
|
||||
'status'=>'解析成功',
|
||||
'anchor_name'=>$anchor_name,
|
||||
'live_url'=>$live_url,
|
||||
'data'=>$data,
|
||||
'source'=>'源码地址:https://github.com/ihmily/DouyinLiveRecorder'
|
||||
];
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
// 封装的CURL函数
|
||||
function get_curl($url,$headers=array(),$cookies=''){
|
||||
$curl=curl_init((string)$url);
|
||||
curl_setopt($curl,CURLOPT_HEADER,false);
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);
|
||||
curl_setopt($curl, CURLOPT_ENCODING, "");
|
||||
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
|
||||
curl_setopt($curl,CURLOPT_HTTPHEADER,$headers);
|
||||
curl_setopt($curl, CURLOPT_COOKIE, $cookies);
|
||||
curl_setopt($curl,CURLOPT_TIMEOUT,20);
|
||||
$data = curl_exec($curl);
|
||||
// var_dump($data);
|
||||
curl_close($curl);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user