核心是选择客户端直传而非服务端上传,thinkphp需调用applyupload签发临时凭证供前端上传,并通过describemediaplayauth获取播放签名实现安全播放,所有操作均以fileid为唯一标识。

ThinkPHP 接入腾讯云点播,核心不是“能不能”,而是「该走客户端上传还是服务端上传」——绝大多数业务场景下,必须用客户端直传,否则视频文件先到你的服务器再发给腾讯云,磁盘和带宽压力会立刻失控。服务端上传只适合小体积、后台批量导入类需求(比如运营后台上传教学视频),且需自行处理分片、断点续传等逻辑。
客户端上传必须由后端签发临时凭证
前端不能直接调用腾讯云 API,必须向你的 ThinkPHP 后端接口申请上传凭证(含 Signature、UploadUrl、FileId 等)。这个过程本质是调用腾讯云 ApplyUpload 接口,由后端用 SecretId 和 SecretKey 签名发起请求。
常见错误现象:
- 前端报错
403 Forbidden或InvalidSignature:多半是后端签名时未正确拼接参数,或时间戳过期(腾讯云要求Timestamp与服务器时间误差 ≤ 15 分钟) - 返回的
UploadUrl无法 PUT 成功:检查是否漏传Authorizationheader,或Content-Type未设为video/mp4等实际 MIME 类型
实操建议:
- 使用腾讯云官方
PHP SDK(v20240718 版本起支持新版 VOD 接口),避免手写签名逻辑出错 - 在
ApplyUpload请求中显式指定SubAppId(专业版必需)、MediaType(如Video)、MediaName(建议用用户 ID + 时间戳防重) - 务必设置
SourceContext字段(如 JSON 字符串{"user_id":123,"scene":"profile_video"}),后续事件通知中可原样收到,用于关联业务数据
ThinkPHP 控制器里怎么调用 ApplyUpload
以 app/controller/VodController.php 为例,关键逻辑如下(不依赖 Laravel 风格封装,纯 ThinkPHP 原生写法):
use think\Controller;
use TencentCloud\Vod\V20240718\VodClient;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Common\Credential;
<p>class VodController extends Controller
{
public function applyUpload()
{
$secretId = config('vod.secret_id'); // 从配置读取
$secretKey = config('vod.secret_key');
$region = 'ap-guangzhou'; // 存储地域,必须与控制台一致
$subAppId = '1234567890'; // 专业版应用 ID</p><pre class="brush:php;toolbar:false;"> $cred = new Credential($secretId, $secretKey);
$profile = [
'region' => $region,
'credential' => $cred,
];
$client = new VodClient($profile);
try {
$params = [
'SubAppId' => $subAppId,
'MediaType' => 'Video',
'MediaName' => 'user_' . session('user_id') . '_' . time(),
'SourceContext' => json_encode(['user_id' => session('user_id')], JSON_UNESCAPED_UNICODE),
];
$resp = $client->ApplyUpload($params);
return json([
'code' => 0,
'data' => [
'upload_url' => $resp->getResponse()->getUploadUrl(),
'file_id' => $resp->getResponse()->getFileId(),
'signature' => $resp->getResponse()->getSignature(),
'expire_time' => $resp->getResponse()->getExpiredTime(),
]
]);
} catch (TencentCloudSDKException $e) {
return json(['code' => -1, 'msg' => $e->getMessage()]);
}
}}
注意点:
-
config('vod.*')必须提前在config/vod.php中定义,SecretKey绝对不可硬编码或写进前端 JS - 返回的
ExpiredTime是 Unix 时间戳,前端上传必须在此时间前完成,建议预留至少 30 秒缓冲 - 若项目用了多存储桶,
ApplyUpload不支持指定 bucket,需通过SubAppId绑定对应桶
播放前必须获取播放签名(PlaySign)
用户上传成功后,拿到 FileId,但直接拼接腾讯云默认播放地址(https://.../xxx.mp4)是公开可盗链的。要启用防盗链,必须调用 DescribeMediaPlayAuth 获取临时播放凭证。
为什么不能跳过这步?
- 腾讯云默认播放 URL 无有效期限制,一旦泄露,视频可被任意爬取
- 即使你开了 Referer 白名单,也无法防止截图工具或代理转发
-
DescribeMediaPlayAuth返回的PlayAuth是加密字符串,配合FileId才能生成带签名的播放 URL
ThinkPHP 中实现示例:
public function getPlayAuth()
{
$fileId = input('file_id');
if (!$fileId) {
return json(['code' => -1, 'msg' => 'missing file_id']);
}
<pre class="brush:php;toolbar:false;">// 同上初始化 client...
try {
$params = ['FileId' => $fileId];
$resp = $client->DescribeMediaPlayAuth($params);
$playAuth = $resp->getResponse()->getPlayAuth();
return json(['code' => 0, 'data' => ['play_auth' => $playAuth]]);
} catch (TencentCloudSDKException $e) {
return json(['code' => -1, 'msg' => $e->getMessage()]);
}}
前端拿到 play_auth 后,传给腾讯云 Web 播放器:player.play({ fileId: 'xxx', playAuth: 'yyy' }) —— 这才是安全播放路径。
删除旧视频时别漏掉 FileId 关联清理
用户更新头像视频、封面视频等场景,常需先删旧再传新。但很多人只删了数据库记录,忘了调用 DeleteMedia 删除腾讯云上的原始文件和转码产物,导致资源持续计费。
容易踩的坑:
-
DeleteMedia是异步操作,返回TaskId,不代表立即删除。若紧接着查DescribeMediaInfos可能仍返回存在 - 如果旧视频已绑定水印/转码模板,删除时默认不删衍生文件;如需彻底清除,得加参数
DeleteParts设为["OriginalFile", "Transcode"] - 调用
DeleteMedia前,务必校验FileId是否归属当前用户(查数据库比对user_id),否则有越权风险
一句话收尾:腾讯云点播的权限模型围绕 FileId 展开,所有操作(上传、播放、删除、转码回调)都依赖它精准锚定资源。漏传、错传、复用过期 FileId,是 80% 以上线上问题的根源。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











