@TiktokAPI
Tiktok API 进阶:视频上传与发布完全指南
嗨,小伙伴们!
上次我们介绍了 Tiktok API 的基础知识,学习了如何进行授权和获取用户信息。
今天我们来聊一个更有趣的话题:如何通过 API 上传和发布视频到 Tiktok!
这可是很多内容创作者、营销团队梦寐以求的功能啊!
想象一下,你可以直接从自己的应用程序发布视频到 Tiktok,甚至可以批量上传、定时发布,是不是很酷?
那就开始今天的学习吧!
一、视频上传 API 概述
首先要明确一点,Tiktok 的视频上传 API 属于高级功能,需要特殊的权限申请。
不是所有开发者都能直接使用这个功能,你需要在 Tiktok 开发者平台申请开通视频上传权限。
申请步骤大致如下:
-
登录 Tiktok 开发者平台
-
进入你的应用设置页面
-
找到"权限申请"或"Features"部分
-
申请"Video Upload"权限,并说明你的用途
-
等待 Tiktok 团队审核(通常需要 1-3 个工作日)
获得权限后,你就可以开始使用视频上传 API 了。
二、视频上传流程
Tiktok 视频上传是一个多步骤的过程,主要包括以下步骤:
- 初始化上传会话
- 分片上传视频数据
- 完成上传并发布视频
下面我们详细介绍每个步骤。
1. 初始化上传会话
首先,我们需要调用 API 创建一个上传会话:
const axios = require('axios');
const fs = require('fs');
const path = require('path');
async function initVideoUpload(accessToken, videoFilePath) {
// 获取视频文件大小
const stats = fs.statSync(videoFilePath);
const fileSizeBytes = stats.size;
try {
const response = await axios.post('https://open.tiktokapis.com/v2/video/init/', {
source_info: {
source: 'FILE_UPLOAD',
video_size: fileSizeBytes,
chunk_size: 1024 * 1024 * 5, // 5MB 分片大小
total_chunk_count: Math.ceil(fileSizeBytes / (1024 * 1024 * 5))
}
}, {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
return response.data.data;
} catch (error) {
console.error('初始化视频上传失败:', error);
throw error;
}
}
初始化成功后,你会收到一个上传 ID 和上传 URL,用于后续的分片上传:
{
"data": {
"upload_id": "7094567890123456789",
"upload_url": "https://upload.tiktokapis.com/video/",
"chunk_size": 5242880
}
}
2. 分片上传视频数据
对于大文件,我们需要将视频分成多个小块(chunk)上传,这样可以提高上传成功率,也支持断点续传:
async function uploadVideoChunk(uploadUrl, uploadId, chunkIndex, chunkData) {
try {
const response = await axios.post(`${uploadUrl}`, chunkData, {
headers: {
'Content-Type': 'application/octet-stream',
'x-upload-id': uploadId,
'x-chunk-index': chunkIndex,
}
});
return response.data;
} catch (error) {
console.error(`上传视频分片 ${chunkIndex} 失败:`, error);
throw error;
}
}
async function uploadVideoFile(uploadInfo, videoFilePath) {
const { upload_id, upload_url, chunk_size } = uploadInfo;
const fileSize = fs.statSync(videoFilePath).size;
const totalChunks = Math.ceil(fileSize / chunk_size);
// 打开文件流
const fileStream = fs.createReadStream(videoFilePath, { highWaterMark: chunk_size });
let chunkIndex = 0;
let uploadedChunks = [];
return new Promise((resolve, reject) => {
fileStream.on('data', async (chunk) => {
// 暂停流,等待当前块上传完成
fileStream.pause();
try {
console.log(`上传分片 ${chunkIndex + 1}/${totalChunks}...`);
const result = await uploadVideoChunk(upload_url, upload_id, chunkIndex, chunk);
uploadedChunks.push({
index: chunkIndex,
size: chunk.length
});
chunkIndex++;
// 继续读取下一块
fileStream.resume();
} catch (error) {
reject(error);
}
});
fileStream.on('end', () => {
console.log('所有分片上传完成');
resolve({
upload_id,
total_chunks: totalChunks,
uploaded_chunks: uploadedChunks
});
});
fileStream.on('error', (error) => {
reject(error);
});
});
}
这段代码会将视频文件分成多个块,然后逐一上传。
每个块上传成功后,我们会收到一个确认响应,表示该块已被服务器接收。
3. 完成上传并发布视频
所有分片上传完成后,我们需要调用 API 告诉 Tiktok 视频已经上传完成,并提供发布相关的信息:
async function completeVideoUpload(accessToken, uploadId, videoInfo) {
try {
const response = await axios.post('https://open.tiktokapis.com/v2/video/publish/', {
upload_id: uploadId,
video_info: {
title: videoInfo.title,
description: videoInfo.description,
visibility: videoInfo.visibility || 'PUBLIC', // 可选: PUBLIC, FRIENDS, PRIVATE
disable_comment: videoInfo.disableComment || false,
disable_duet: videoInfo.disableDuet || false,
disable_stitch: videoInfo.disableStitch || false,
privacy_level: videoInfo.privacyLevel || 'PUBLIC',
scheduled_publish_time: videoInfo.scheduledPublishTime || 0, // Unix 时间戳,0表示立即发布
branded_content_toggle: videoInfo.brandedContentToggle || false
}
}, {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
return response.data.data;
} catch (error) {
console.error('完成视频上传失败:', error);
throw error;
}
}
发布成功后,我们会收到一个包含视频 ID 的响应:
{
"data": {
"video_id": "7094567890123456789",
"share_url": "https://www.tiktok.com/@username/video/7094567890123456789"
}
}
三、完整的视频上传示例
下面是一个完整的视频上传流程示例,整合了上面的所有步骤:
const express = require('express');
const multer = require('multer');
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const app = express();
const upload = multer({ dest: 'uploads/' });
// 上传视频的路由
app.post('/upload-to-tiktok', upload.single('video'), async (req, res) => {
try {
// 获取上传的文件
const videoFile = req.file;
const accessToken = req.body.accessToken; // 从请求中获取访问令牌
if (!videoFile) {
return res.status(400).json({ error: '没有上传视频文件' });
}
// 准备视频信息
const videoInfo = {
title: req.body.title || '我的 TikTok 视频',
description: req.body.description || '通过 API 上传的视频 #tiktok #api',
visibility: req.body.visibility || 'PUBLIC'
};
// 1. 初始化上传
console.log('初始化视频上传...');
const uploadInfo = await initVideoUpload(accessToken, videoFile.path);
// 2. 分片上传视频
console.log('开始上传视频分片...');
const uploadResult = await uploadVideoFile(uploadInfo, videoFile.path);
// 3. 完成上传并发布
console.log('完成视频上传并发布...');
const publishResult = await completeVideoUpload(accessToken, uploadInfo.upload_id, videoInfo);
// 清理临时文件
fs.unlinkSync(videoFile.path);
// 返回成功结果
res.json({
success: true,
video_id: publishResult.video_id,
share_url: publishResult.share_url
});
} catch (error) {
console.error('上传视频到 TikTok 失败:', error);
// 清理临时文件(如果存在)
if (req.file && fs.existsSync(req.file.path)) {
fs.unlinkSync(req.file.path);
}
res.status(500).json({
success: false,
error: error.message || '上传失败'
});
}
});
// 启动服务器
app.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});
这个例子展示了如何创建一个 Web 服务,接收视频文件并上传到 Tiktok。
用户可以通过表单提交视频文件和相关信息,服务器会处理上传过程并返回结果。
四、高级功能:定时发布与草稿
Tiktok API 还支持一些高级功能,比如定时发布和保存为草稿:
1. 定时发布
你可以设置一个未来的时间点发布视频,这对于内容计划非常有用:
// 设置 24 小时后发布
const tomorrow = Math.floor(Date.now() / 1000) + 24 * 60 * 60;
const videoInfo = {
title: '明天会发布的视频',
description: '这个视频将在明天自动发布 #定时发布',
scheduledPublishTime: tomorrow
};
// 其他代码不变...
2. 保存为草稿
你可以将视频上传后先保存为草稿,而不是直接发布:
const videoInfo = {
title: '草稿视频',
description: '这是一个草稿视频,需要手动发布',
visibility: 'PRIVATE', // 设置为私密
isDraft: true // 保存为草稿
};
// 调用完成上传 API 时,添加 draft 参数
async function completeVideoUploadAsDraft(accessToken, uploadId, videoInfo) {
try {
const response = await axios.post('https://open.tiktokapis.com/v2/video/publish/', {
upload_id: uploadId,
video_info: {
// ... 其他字段
},
publish_mode: 'DRAFT' // 保存为草稿
}, {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
return response.data.data;
} catch (error) {
console.error('保存为草稿失败:', error);
throw error;
}
}
用户可以稍后在 Tiktok 应用中手动发布这些草稿视频。
五、视频上传的最佳实践
在实际开发中,有一些最佳实践可以帮助你更好地实现视频上传功能:
1. 视频格式和质量控制
Tiktok 对上传的视频有一定的格式和大小要求:
function checkVideoCompatibility(videoPath) {
// 使用 ffprobe 或其他库获取视频信息
const videoInfo = getVideoMetadata(videoPath);
const recommendations = [];
// 检查视频时长 (Tiktok 支持 5 秒至 10 分钟)
if (videoInfo.duration < 5) {
recommendations.push('视频过短,TikTok 要求至少 5 秒');
} else if (videoInfo.duration > 600) {
recommendations.push('视频过长,TikTok 一般支持最长 10 分钟');
}
// 检查分辨率 (推荐 1080x1920)
if (videoInfo.width !== 1080 || videoInfo.height !== 1920) {
recommendations.push(`当前分辨率 ${videoInfo.width}x${videoInfo.height},推荐使用 1080x1920`);
}
// 检查格式 (推荐 mp4)
if (videoInfo.format !== 'mp4') {
recommendations.push(`当前格式 ${videoInfo.format},推荐使用 mp4`);
}
return {
isCompatible: recommendations.length === 0,
recommendations
};
}
在上传前检查视频的兼容性,可以提高上传成功率和视频质量。
2. 断点续传实现
对于大文件上传,断点续传是非常重要的功能:
async function resumableUpload(accessToken, videoFilePath, uploadInfo = null) {
// 如果没有上传信息,初始化一个新的上传
if (!uploadInfo) {
uploadInfo = await initVideoUpload(accessToken, videoFilePath);
// 保存上传信息到本地存储,用于断点续传
saveUploadInfoToStorage(videoFilePath, uploadInfo);
}
try {
// 上传视频文件
const uploadResult = await uploadVideoFile(uploadInfo, videoFilePath);
// 上传成功后,删除本地存储的上传信息
removeUploadInfoFromStorage(videoFilePath);
return uploadResult;
} catch (error) {
// 上传失败,保留上传信息,下次可以继续
console.error('上传中断:', error);
throw error;
}
}
// 使用示例
app.post('/resumable-upload', async (req, res) => {
const videoFilePath = req.body.videoPath;
const accessToken = req.body.accessToken;
// 检查是否有未完成的上传
const savedUploadInfo = getUploadInfoFromStorage(videoFilePath);
try {
const result = await resumableUpload(accessToken, videoFilePath, savedUploadInfo);
res.json(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
这个实现会在上传开始时保存上传信息,如果上传中断,下次可以从断点继续。
3. 上传进度跟踪
对于用户体验,上传进度跟踪非常重要:
async function uploadVideoFileWithProgress(uploadInfo, videoFilePath, progressCallback) {
const { upload_id, upload_url, chunk_size } = uploadInfo;
const fileSize = fs.statSync(videoFilePath).size;
const totalChunks = Math.ceil(fileSize / chunk_size);
let chunkIndex = 0;
let totalBytesUploaded = 0;
// 打开文件流
const fileStream = fs.createReadStream(videoFilePath, { highWaterMark: chunk_size });
return new Promise((resolve, reject) => {
fileStream.on('data', async (chunk) => {
fileStream.pause();
try {
await uploadVideoChunk(upload_url, upload_id, chunkIndex, chunk);
// 更新上传进度
totalBytesUploaded += chunk.length;
const progress = Math.min(100, Math.round((totalBytesUploaded / fileSize) * 100));
// 调用进度回调
progressCallback({
chunkIndex,
totalChunks,
bytesUploaded: totalBytesUploaded,
totalBytes: fileSize,
percentage: progress
});
chunkIndex++;
fileStream.resume();
} catch (error) {
reject(error);
}
});
fileStream.on('end', () => {
resolve({
upload_id,
total_chunks: totalChunks
});
});
fileStream.on('error', (error) => {
reject(error);
});
});
}
// 使用 WebSocket 向客户端推送进度
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('WebSocket 客户端已连接');
// 处理上传请求
ws.on('message', async (message) => {
const data = JSON.parse(message);
if (data.type === 'upload') {
try {
// 初始化上传
const uploadInfo = await initVideoUpload(data.accessToken, data.videoPath);
// 上传视频,并发送进度更新
await uploadVideoFileWithProgress(uploadInfo, data.videoPath, (progress) => {
ws.send(JSON.stringify({
type: 'progress',
data: progress
}));
});
// 完成上传
const result = await completeVideoUpload(data.accessToken, uploadInfo.upload_id, data.videoInfo);
// 发送成功消息
ws.send(JSON.stringify({
type: 'complete',
data: result
}));
} catch (error) {
// 发送错误消息
ws.send(JSON.stringify({
type: 'error',
message: error.message
}));
}
}
});
});
通过 WebSocket,你可以实时向前端发送上传进度,提供更好的用户体验。
六、实用案例:批量视频上传工具
最后,让我们来看一个实用的案例:如何开发一个批量视频上传工具。
这对于内容创作者和营销团队特别有用:
const fs = require('fs');
const path = require('path');
const readline = require('readline');
// 批量上传功能
async function batchUploadVideos(accessToken, videoFolder, hashtagsFile = null) {
// 读取文件夹中的所有视频
const files = fs.readdirSync(videoFolder)
.filter(file => ['.mp4', '.mov'].includes(path.extname(file).toLowerCase()))
.map(file => path.join(videoFolder, file));
if (files.length === 0) {
console.log('没有找到视频文件');
return;
}
console.log(`找到 ${files.length} 个视频文件`);
// 读取话题标签(如果提供了文件)
let hashtags = [];
if (hashtagsFile && fs.existsSync(hashtagsFile)) {
const content = fs.readFileSync(hashtagsFile, 'utf8');
hashtags = content.split('\n')
.map(line => line.trim())
.filter(tag => tag.length > 0)
.map(tag => tag.startsWith('#') ? tag : `#${tag}`);
console.log(`从文件中加载了 ${hashtags.length} 个话题标签`);
}
// 随机选择话题标签的函数
function getRandomHashtags(count = 5) {
if (hashtags.length === 0) return '';
const shuffled = [...hashtags].sort(() => 0.5 - Math.random());
return shuffled.slice(0, Math.min(count, hashtags.length)).join(' ');
}
// 询问用户确认
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const answer = await new Promise(resolve => {
rl.question(`准备上传 ${files.length} 个视频文件,确认继续?(y/n) `, resolve);
});
rl.close();
if (answer.toLowerCase() !== 'y') {
console.log('操作已取消');
return;
}
// 开始批量上传
console.log('开始批量上传...');
let successCount = 0;
let failCount = 0;
for (let i = 0; i < files.length; i++) {
const videoFile = files[i];
const fileName = path.basename(videoFile, path.extname(videoFile));
console.log(`[${i+1}/${files.length}] 上传: ${fileName}`);
try {
// 准备视频信息
const videoInfo = {
title: fileName,
description: `${fileName} ${getRandomHashtags()}`,
visibility: 'PUBLIC'
};
// 上传流程
const uploadInfo = await initVideoUpload(accessToken, videoFile);
await uploadVideoFile(uploadInfo, videoFile);
const result = await completeVideoUpload(accessToken, uploadInfo.upload_id, videoInfo);
console.log(`✓ 上传成功: ${result.share_url}`);
successCount++;
// 避免频率限制,在每次上传之间等待一段时间
if (i < files.length - 1) {
console.log('等待 30 秒后继续下一个上传...');
await new Promise(resolve => setTimeout(resolve, 30000));
}
} catch (error) {
console.error(`✗ 上传失败: ${error.message}`);
failCount++;
}
}
console.log('\n批量上传完成!');
console.log(`总计: ${files.length} 个视频`);
console.log(`成功: ${successCount} 个`);
console.log(`失败: ${failCount} 个`);
}
// 使用示例
batchUploadVideos(
'YOUR_ACCESS_TOKEN',
'./videos',
'./hashtags.txt'
);
这个工具可以帮助内容创作者一次性上传多个视频,并自动添加话题标签,大大提高了工作效率。
七、总结与展望
今天我们深入学习了 Tiktok API 的视频上传功能,包括:
-
如何申请视频上传 API 权限
-
视频上传的完整流程(初始化、分片上传、完成发布)
-
高级功能(定时发布、保存草稿)
-
最佳实践(格式控制、断点续传、进度跟踪)
-
实用案例(批量上传工具)
通过这些功能,你可以为你的应用添加强大的 Tiktok 集成能力,自动化内容发布流程,提高工作效率。
不过需要注意的是,Tiktok API 的使用需要遵守平台的规则和政策,确保你的应用合规使用 API 功能。
在下一篇文章中,我们将探讨如何使用 Tiktok API 获取数据分析和洞察,帮助你更好地理解内容表现和受众特征。
如果你有什么问题或建议,欢迎在评论区留言交流~