抖音视频是个好东西,可以1080P,无水印解析,唯一的缺点就是要填写 cookie。
播放演示
已获取的长久视频地址
代码:
修复了移动端总是 "code": 500, 无法正常获取视频链接的BUG。
<?php
/**
* 抖音视频解析接口
* 用法:/parse.php?url=抖音分享链接
*/
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
// ==================== 配置 ====================
$customCookie = 'ttwid=1%7CRejU7p-9wM-Qu_kG3IwTGTUCLrZHqB14nkyV-aaViJI%7C1790666684%7Cc31a024ddfe52459acaff945bb806643c229e0682cbced738176c70945f676a2'; // 抖音 Cookie(可从浏览器开发者工具获取 www.douyin.com 标头 set-cookie 的 ttwid 的值)
$defaultRatio = '1080p'; // 默认画质
// =============================================
$shareUrl = $_GET['url'] ?? '';
if (!$shareUrl) {
echo json_encode(['code' => 400, 'msg' => '缺少 url 参数'], JSON_UNESCAPED_UNICODE);
exit;
}
try {
$videoId = getDouyinVideoId($shareUrl, $customCookie);
if (!$videoId) {
throw new Exception('解析失败,可能被风控或页面结构已变化');
}
$playUrl = "https://aweme.snssdk.com/aweme/v1/play/?video_id={$videoId}&ratio={$defaultRatio}&line=0";
$result = [
'code' => 0,
'msg' => 'success',
'url' => $playUrl,
];
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
} catch (Exception $e) {
echo json_encode(['code' => 500, 'msg' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
}
function curlInit(string $url, string $cookie = '', bool $follow = true, array $headers = [])
{
$ch = curl_init();
$opt = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => $follow,
CURLOPT_MAXREDIRS => 5,
CURLOPT_TIMEOUT => 15,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_USERAGENT => 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
];
if ($cookie) $opt[CURLOPT_COOKIE] = $cookie;
if ($headers) $opt[CURLOPT_HTTPHEADER] = $headers;
curl_setopt_array($ch, $opt);
return $ch;
}
function expandShortUrl(string $shortUrl, string $cookie = ''): ?string
{
$ch = curlInit($shortUrl, $cookie);
$ok = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$effectiveUrl = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
curl_close($ch);
return ($ok !== false && $httpCode < 400 && $effectiveUrl) ? $effectiveUrl : null;
}
function extractAwemeId(string $longUrl): ?string
{
return preg_match('/(?:video|note)\/(\d+)/', $longUrl, $m) ? $m[1] : null;
}
/**
* 判断字符串是否为抖音 video_id(v0 / v1 / v1e ... 前缀 + 数字字母)
*/
function isVideoId(string $value): bool
{
return (bool) preg_match('/^v[0-9][0-9a-z]+/i', $value);
}
function getVideoIdFromSharePage(string $awemeId, string $cookie = ''): ?string
{
$ch = curlInit("https://www.iesdouyin.com/share/video/{$awemeId}", $cookie, true, [
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: zh-CN,zh;q=0.9',
'Referer: https://www.douyin.com/',
]);
$html = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($html === false || $httpCode >= 400) return null;
if (!preg_match('/window\._ROUTER_DATA\s*=\s*(.*?)<\/script>/s', $html, $m) &&
!preg_match('/window\.__INITIAL_STATE__\s*=\s*(.*?)<\/script>/s', $html, $m)) {
return null;
}
$data = json_decode(rtrim(trim($m[1]), ';'), true);
if (!is_array($data)) return null;
$paths = [
['loaderData', 'video_(id)/page', 'videoInfoRes', 'item_list', 0, 'video', 'play_addr', 'uri'],
['videoInfoRes', 'item_list', 0, 'video', 'play_addr', 'uri'],
['item_list', 0, 'video', 'play_addr', 'uri'],
];
foreach ($paths as $path) {
$value = $data;
foreach ($path as $key) {
if (is_array($value) && array_key_exists($key, $value)) {
$value = $value[$key];
} else {
$value = null;
break;
}
}
if (is_string($value) && isVideoId($value)) return $value;
}
return findVideoId($data);
}
function findVideoId($data): ?string
{
if (!is_array($data)) return null;
foreach ($data as $value) {
if (is_string($value) && isVideoId($value)) {
return $value;
}
$found = findVideoId($value);
if ($found !== null) return $found;
}
return null;
}
function getDouyinVideoId(string $shareUrl, string $cookie = ''): ?string
{
$longUrl = expandShortUrl($shareUrl, $cookie) ?: $shareUrl;
$awemeId = extractAwemeId($longUrl);
return $awemeId ? getVideoIdFromSharePage($awemeId, $cookie) : null;
}cookie可以是一个未登陆账号的 ttwid 值,获取方法:电脑浏览器打开抖音网页,开发者工具获取 www.douyin.com 标头 set-cookie 的 ttwid 的值,一般 cookie 有效期大概一年左右。
url 的值就是长久视频链接,一般不会变动。
注意
- 如果要在网页上引用,记得给网页头部添加
<meta name="referrer" content="no-referrer">完全隐藏请求的来源信息,否则会被跨域拦截。 - 如果是typecho引用,可在主题头部添加中更灵活的
<meta name="referrer" content="same-origin">,防止没有头请求无法提交评论。
评论 (0)