视频剪辑、素材收集等场景常需要获取抖音视频的直链地址。本文梳理从分享短链视频/封面/音乐 URL 的解析思路(仅供学习研究,请遵守平台服务条款与版权法规)。

整体流程

分享短链 (v.douyin.com/xxx)
↓ 关闭自动重定向,捕获 302
重定向地址 (iesdouyin.com/share/video/{aweme_id}/...)
↓ 提取 aweme_id
官方接口 (/web/api/v2/aweme/iteminfo/)
↓ 解析 JSON
视频地址 / 封面 / 背景音乐

第一步:获取分享短链

用户在抖音 App 中点击「复制链接」,得到类似:

https://v.douyin.com/eReT43D/

这是短链,需要展开才能拿到真实的 aweme_id(视频编号)。

第二步:关闭重定向,捕获真实 URL

直接 GET 短链时,服务端会返回 302 重定向www.iesdouyin.com/share/video/...,中间可能夹杂验证码页面。

调试技巧:

  1. 在 Postman / curl 中关闭自动跟随重定向
  2. 查看响应头 Location 字段
  3. 得到重定向前的完整 URL
curl -I "https://v.douyin.com/eReT43D/" \
-H "User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)"

响应示例:

HTTP/1.1 302 Found
Location: https://www.iesdouyin.com/share/video/6929752969407712527/?region=CN&...

第三步:从 URL 提取 aweme_id

从重定向 URL 的路径中截取视频 ID:

const { URL } = require('url');

const redirectUrl =
'https://www.iesdouyin.com/share/video/6929752969407712527/?region=CN&mid=...';

const pathname = new URL(redirectUrl).pathname;
// /share/video/6929752969407712527/
const awemeId = pathname.split('/')[3];
// => "6929752969407712527"

Rust 等价写法:

fn extract_aweme_id(url: &str) -> Option<String> {
let path = url::Url::parse(url).ok()?.path();
path.split('/').nth(3).map(|s| s.to_string())
}

第四步:调用官方 iteminfo 接口

GET https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids={aweme_id}

请求时需携带常见浏览器 UA,部分时期还需要 Cookie 或签名参数(接口会不定期升级)。

curl "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=6929752969407712527" \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
-H "Referer: https://www.douyin.com/"

第五步:解析返回 JSON

成功时 status_code0,核心数据在 item_list[0]

{
"status_code": 0,
"item_list": [{
"aweme_id": "6929752969407712527",
"desc": "视频标题",
"video": {
"play_addr": {
"url_list": [
"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=xxx&ratio=720p&line=0"
]
},
"cover": { "url_list": ["https://p3-sign.douyinpic.com/..."] },
"origin_cover": { "url_list": ["https://p3-sign.douyinpic.com/..."] },
"has_watermark": true
},
"music": {
"play_url": {
"url_list": ["https://sf6-cdn-tos.douyinstatic.com/obj/ies-music/xxx.mp3"]
}
}
}]
}

关键字段

字段路径含义
item_list[0].desc视频标题/描述
video.play_addr.url_list[0]带水印播放地址
video.origin_cover.url_list[0]封面图
music.play_url.url_list[0]背景音乐
video.has_watermark是否含水印

提取示例:

const item = data.item_list[0];

const videoUrl = item.video.play_addr.url_list[0];
const coverUrl = item.video.origin_cover.url_list[0];
const musicUrl = item.music.play_url.url_list[0];

关于无水印

play_addr 返回的 URL 通常带 playwm(watermark),要获取无水印版本可将 URL 中的 playwm 替换为 play,但:

  • 该技巧随时可能失效
  • 部分视频有加密或时效签名(x-signature 参数)
  • 生产环境应评估合规风险

第六步:视频下载

浏览器直接打开

videoUrl 粘贴到浏览器地址栏即可播放或另存为。

前端 Blob 下载

async function downloadVideo(url, filename = 'video.mp4') {
const res = await fetch(url);
const blob = await res.blob();
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
URL.revokeObjectURL(link.href);
}

服务端代理下载

跨域或防盗链场景下,可由后端转发请求:

客户端 → 你的服务器 → 抖音 CDN → 返回视频流

注意控制带宽与请求频率,避免被封 IP。

常见问题

现象可能原因
短链返回验证码页IP 被风控,换 UA/Cookie 或降低频率
item_list 为空aweme_id 错误或视频已删除/私密
播放地址 403签名过期,需重新请求接口
playwm 替换无效接口升级,需跟进新版解析方案

与本站 live_crawler 的关系

live_crawler 项目专注于 直播源聚合与 CMS 解析/getliveurl/tvbox 等),抖音短视频解析属于独立的爬虫领域。若需集成,建议:

  1. 单独模块封装,与直播源逻辑解耦
  2. 加快照缓存,避免重复请求
  3. 接口变更时只改解析层,不影响主业务

小结

抖音视频解析的本质是:短链 → 重定向 → aweme_id → iteminfo API → 字段提取。掌握这条链路后,无论用 Node.js、Python 还是 Rust 实现,思路都是一致的。实际开发中需持续关注接口变动与合规要求。