beervid-app-cli 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,468 @@
1
+ # 故障排查指南
2
+
3
+ 本文档帮助你快速定位和解决 BEERVID Open API 集成中的常见问题。
4
+
5
+ ## 目录
6
+
7
+ 1. [认证问题](#认证问题)
8
+ 2. [上传问题](#上传问题)
9
+ 3. [发布问题](#发布问题)
10
+ 4. [轮询问题](#轮询问题)
11
+ 5. [查询问题](#查询问题)
12
+ 6. [网络问题](#网络问题)
13
+ 7. [调试技巧](#调试技巧)
14
+
15
+ ---
16
+
17
+ ## 认证问题
18
+
19
+ ### 错误:401 Unauthorized
20
+
21
+ **症状:**
22
+ ```json
23
+ {
24
+ "code": 401,
25
+ "message": "Unauthorized",
26
+ "success": false
27
+ }
28
+ ```
29
+
30
+ **可能原因:**
31
+ 1. `BEERVID_APP_KEY` 未设置或错误
32
+ 2. API Key 已过期或被撤销
33
+ 3. 请求头 `X-API-KEY` 未正确设置
34
+
35
+ **解决方案:**
36
+
37
+ ```bash
38
+ # 检查当前配置
39
+ beervid config --show
40
+
41
+ # 重新设置 API Key
42
+ beervid config --app-key "your-correct-api-key"
43
+
44
+ # 或使用环境变量
45
+ export BEERVID_APP_KEY="your-correct-api-key"
46
+ ```
47
+
48
+ **验证:**
49
+ ```bash
50
+ # 测试 API Key 是否有效
51
+ beervid get-oauth-url --type tt
52
+ ```
53
+
54
+ ### 错误:X-API-KEY header is required
55
+
56
+ **症状:**
57
+ API 返回缺少认证头的错误。
58
+
59
+ **解决方案:**
60
+
61
+ 检查你的代码是否正确设置了请求头:
62
+
63
+ ```typescript
64
+ const headers = {
65
+ 'X-API-KEY': process.env.BEERVID_APP_KEY,
66
+ 'Content-Type': 'application/json'
67
+ }
68
+ ```
69
+
70
+ ---
71
+
72
+ ## 上传问题
73
+
74
+ ### 错误:上传凭证获取失败
75
+
76
+ **症状:**
77
+ ```json
78
+ {
79
+ "code": 400,
80
+ "message": "Invalid account type"
81
+ }
82
+ ```
83
+
84
+ **可能原因:**
85
+ - TTS 上传需要 `creatorUserOpenId`,但你传了 `businessId`
86
+ - TT 上传不需要额外参数,但你传了 `creatorUserOpenId`
87
+
88
+ **解决方案:**
89
+
90
+ ```bash
91
+ # TT 普通上传(不需要额外参数)
92
+ beervid upload --file ./video.mp4
93
+
94
+ # TTS 上传(需要 creator-id)
95
+ beervid upload --file ./video.mp4 --type tts --creator-id "open_user_abc"
96
+ ```
97
+
98
+ ### 错误:文件上传超时
99
+
100
+ **症状:**
101
+ 上传大文件时请求超时。
102
+
103
+ **解决方案:**
104
+
105
+ 1. **检查文件大小:** TikTok 限制视频大小通常为 4GB
106
+ 2. **检查网络连接:** 确保网络稳定
107
+ 3. **增加超时时间:** 如果使用代码集成,增加请求超时
108
+
109
+ ```typescript
110
+ // 示例:增加超时时间
111
+ const controller = new AbortController()
112
+ const timeout = setTimeout(() => controller.abort(), 300000) // 5分钟
113
+
114
+ try {
115
+ await fetch(uploadUrl, {
116
+ method: 'POST',
117
+ body: formData,
118
+ signal: controller.signal
119
+ })
120
+ } finally {
121
+ clearTimeout(timeout)
122
+ }
123
+ ```
124
+
125
+ ### 错误:Invalid file format
126
+
127
+ **症状:**
128
+ ```json
129
+ {
130
+ "code": 400,
131
+ "message": "Unsupported video format"
132
+ }
133
+ ```
134
+
135
+ **解决方案:**
136
+
137
+ 确保视频格式符合 TikTok 要求:
138
+ - 支持格式:MP4, MOV, MPEG, 3GP, AVI, WebM
139
+ - 推荐格式:MP4 (H.264 编码)
140
+ - 分辨率:最小 720p,推荐 1080p
141
+ - 时长:3秒 - 10分钟
142
+
143
+ ---
144
+
145
+ ## 发布问题
146
+
147
+ ### 错误:businessId not found
148
+
149
+ **症状:**
150
+ ```json
151
+ {
152
+ "code": 404,
153
+ "message": "Account not found"
154
+ }
155
+ ```
156
+
157
+ **可能原因:**
158
+ 1. `businessId` 或 `creatorUserOpenId` 错误
159
+ 2. 账号未完成 OAuth 授权
160
+ 3. 账号已被解绑
161
+
162
+ **解决方案:**
163
+
164
+ ```bash
165
+ # 验证账号是否存在
166
+ beervid get-account-info --type TT --account-id "your-business-id"
167
+
168
+ # 如果账号不存在,重新获取授权
169
+ beervid get-oauth-url --type tt
170
+ ```
171
+
172
+ ### 错误:productTitle too long
173
+
174
+ **症状:**
175
+ TTS 发布时提示商品标题过长。
176
+
177
+ **解决方案:**
178
+
179
+ `productTitle` 最多 30 个字符,需要提前截断:
180
+
181
+ ```typescript
182
+ const productTitle = originalTitle.length > 30
183
+ ? originalTitle.slice(0, 30)
184
+ : originalTitle
185
+ ```
186
+
187
+ ### 错误:Invalid video URL
188
+
189
+ **症状:**
190
+ TT 普通发布时提示视频 URL 无效。
191
+
192
+ **可能原因:**
193
+ 1. `videoUrl` 不是可公开访问的 URL
194
+ 2. URL 已过期
195
+ 3. URL 格式错误
196
+
197
+ **解决方案:**
198
+
199
+ 确保 `videoUrl` 是上传接口返回的 `fileUrl`:
200
+
201
+ ```bash
202
+ # 先上传,获取 fileUrl
203
+ beervid upload --file ./video.mp4
204
+
205
+ # 使用返回的 fileUrl 发布
206
+ beervid publish --type normal \
207
+ --business-id "biz_123" \
208
+ --video-url "https://cdn.beervid.ai/uploads/xxx.mp4"
209
+ ```
210
+
211
+ ---
212
+
213
+ ## 轮询问题
214
+
215
+ ### 问题:轮询一直不返回 PUBLISH_COMPLETE
216
+
217
+ **症状:**
218
+ 轮询状态一直是 `PROCESSING_DOWNLOAD` 或 `SEND_TO_USER_INBOX`。
219
+
220
+ **可能原因:**
221
+ 1. TikTok 平台处理较慢(正常情况)
222
+ 2. 视频文件有问题
223
+ 3. TikTok 账号有限制
224
+
225
+ **解决方案:**
226
+
227
+ 1. **增加轮询次数和间隔:**
228
+
229
+ ```bash
230
+ beervid poll-status \
231
+ --business-id "biz_123" \
232
+ --share-id "share_abc" \
233
+ --interval 10000 \
234
+ --max-polls 60
235
+ ```
236
+
237
+ 2. **检查状态详情:**
238
+
239
+ ```typescript
240
+ // 查看完整状态信息
241
+ const status = await pollStatus(businessId, shareId)
242
+ console.log('Status:', status.status)
243
+ console.log('Error:', status.error_code, status.error_message)
244
+ ```
245
+
246
+ 3. **常见状态及含义:**
247
+
248
+ | 状态 | 含义 | 是否正常 |
249
+ |------|------|----------|
250
+ | `PROCESSING_DOWNLOAD` | TikTok 正在下载视频 | 正常,继续等待 |
251
+ | `SEND_TO_USER_INBOX` | 视频已发送到收件箱 | 正常,继续等待 |
252
+ | `PUBLISH_COMPLETE` | 发布完成 | 成功 |
253
+ | `FAILED` | 发布失败 | 失败,检查错误信息 |
254
+
255
+ ### 问题:post_ids 为空
256
+
257
+ **症状:**
258
+ 状态是 `PUBLISH_COMPLETE`,但 `post_ids` 数组为空。
259
+
260
+ **解决方案:**
261
+
262
+ 这通常表示视频还在处理中,需要继续轮询:
263
+
264
+ ```typescript
265
+ // 正确的完成判断
266
+ const isComplete =
267
+ status.status === 'PUBLISH_COMPLETE' &&
268
+ status.post_ids &&
269
+ status.post_ids.length > 0
270
+ ```
271
+
272
+ ---
273
+
274
+ ## 查询问题
275
+
276
+ ### 错误:Only TT accounts can query video data
277
+
278
+ **症状:**
279
+ 使用 TTS 账号查询视频数据时报错。
280
+
281
+ **解决方案:**
282
+
283
+ 视频数据查询仅支持 TT 账号:
284
+
285
+ ```bash
286
+ # 正确:使用 TT 账号的 businessId
287
+ beervid query-video \
288
+ --business-id "7281234567890" \
289
+ --item-ids "7123456789012345678"
290
+
291
+ # 错误:使用 TTS 账号的 creatorUserOpenId
292
+ # TTS 账号不支持视频数据查询
293
+ ```
294
+
295
+ 如果同一达人已经完成了 TTS 授权,但你还想查询该账号的视频数据:
296
+
297
+ - 还需要额外完成一次 TT 授权
298
+ - 官方当前没有提供 `uno_id` 这类 TT/TTS 强关联字段
299
+ - 当前推荐在你方系统里通过 `account/info` 返回的 `username` 建立 TT/TTS 关联
300
+ - 查数时使用关联后的 TT `businessId`,不要直接使用 TTS `creatorUserOpenId`
301
+
302
+ ### 问题:查询返回的字段不一致
303
+
304
+ **症状:**
305
+ 有时返回 `playCount`,有时返回 `play_count`。
306
+
307
+ **解决方案:**
308
+
309
+ API 可能同时返回 camelCase 和 snake_case 字段,建议兼容处理:
310
+
311
+ ```typescript
312
+ const playCount = data.playCount ?? data.play_count ?? 0
313
+ const likeCount = data.likeCount ?? data.like_count ?? 0
314
+ ```
315
+
316
+ ---
317
+
318
+ ## 网络问题
319
+
320
+ ### 错误:ECONNREFUSED 或 ETIMEDOUT
321
+
322
+ **症状:**
323
+ 请求无法连接到服务器。
324
+
325
+ **解决方案:**
326
+
327
+ 1. **检查 BASE_URL 配置:**
328
+
329
+ ```bash
330
+ beervid config --show
331
+
332
+ # 确保 BASE_URL 正确
333
+ beervid config --base-url "https://open.beervid.ai"
334
+ ```
335
+
336
+ 2. **检查网络连接:**
337
+
338
+ ```bash
339
+ # 测试网络连通性
340
+ curl -I https://open.beervid.ai/api/v1/open/thirdparty-auth/tt-url
341
+ ```
342
+
343
+ 3. **检查防火墙和代理:**
344
+
345
+ 如果在企业网络环境,可能需要配置代理:
346
+
347
+ ```bash
348
+ export HTTP_PROXY="http://proxy.company.com:8080"
349
+ export HTTPS_PROXY="http://proxy.company.com:8080"
350
+ ```
351
+
352
+ ### 错误:SSL certificate problem
353
+
354
+ **症状:**
355
+ SSL 证书验证失败。
356
+
357
+ **解决方案:**
358
+
359
+ ```bash
360
+ # 临时禁用 SSL 验证(仅用于调试,生产环境不推荐)
361
+ export NODE_TLS_REJECT_UNAUTHORIZED=0
362
+
363
+ # 更好的方案:更新系统证书
364
+ # macOS
365
+ brew install ca-certificates
366
+
367
+ # Ubuntu/Debian
368
+ sudo apt-get update && sudo apt-get install ca-certificates
369
+ ```
370
+
371
+ ---
372
+
373
+ ## 调试技巧
374
+
375
+ ### 1. 启用详细日志
376
+
377
+ ```bash
378
+ # 设置环境变量启用调试模式
379
+ export DEBUG=beervid:*
380
+
381
+ # 运行命令查看详细日志
382
+ beervid upload --file ./video.mp4
383
+ ```
384
+
385
+ ### 2. 使用 --verbose 标志
386
+
387
+ ```bash
388
+ # 如果 CLI 支持 verbose 模式
389
+ beervid publish-tt-flow \
390
+ --business-id "biz_123" \
391
+ --file ./video.mp4 \
392
+ --verbose
393
+ ```
394
+
395
+ ### 3. 检查原始响应
396
+
397
+ 在代码中打印完整响应:
398
+
399
+ ```typescript
400
+ try {
401
+ const response = await openApiPost('/api/v1/open/tiktok/video/publish', data)
402
+ console.log('Full response:', JSON.stringify(response, null, 2))
403
+ } catch (error) {
404
+ console.error('Error details:', error)
405
+ }
406
+ ```
407
+
408
+ ### 4. 使用 curl 测试 API
409
+
410
+ ```bash
411
+ # 测试获取授权链接
412
+ curl -X GET \
413
+ -H "X-API-KEY: your-api-key" \
414
+ https://open.beervid.ai/api/v1/open/thirdparty-auth/tt-url
415
+
416
+ # 测试账号信息查询
417
+ curl -X POST \
418
+ -H "X-API-KEY: your-api-key" \
419
+ -H "Content-Type: application/json" \
420
+ -d '{"accountType":"TT","accountId":"7281234567890"}' \
421
+ https://open.beervid.ai/api/v1/open/account/info
422
+ ```
423
+
424
+ ### 5. 检查 CLI 版本
425
+
426
+ ```bash
427
+ # 确保使用最新版本
428
+ npm list -g beervid-app-cli
429
+
430
+ # 更新到最新版本
431
+ npm update -g beervid-app-cli
432
+ ```
433
+
434
+ ### 6. 清理本地配置
435
+
436
+ ```bash
437
+ # 查看配置文件位置
438
+ ls -la ~/.beervid/
439
+
440
+ # 删除配置文件重新开始
441
+ rm -rf ~/.beervid/config.json
442
+
443
+ # 重新配置
444
+ beervid config --app-key "your-api-key"
445
+ ```
446
+
447
+ ---
448
+
449
+ ## 常见错误码速查
450
+
451
+ | 错误码 | 含义 | 解决方案 |
452
+ |--------|------|----------|
453
+ | 400 | 请求参数错误 | 检查参数格式和必填字段 |
454
+ | 401 | 认证失败 | 检查 API Key 是否正确 |
455
+ | 403 | 权限不足 | 检查账号权限或 API Key 权限 |
456
+ | 404 | 资源不存在 | 检查 ID 是否正确 |
457
+ | 429 | 请求过于频繁 | 降低请求频率,参考限流说明 |
458
+ | 500 | 服务器错误 | 稍后重试,或联系技术支持 |
459
+
460
+ ---
461
+
462
+ ## 仍然无法解决?
463
+
464
+ 1. **查看完整 API 文档:** [references/api-reference.md](../references/api-reference.md)
465
+ 2. **查看 FAQ:** [FAQ.md](../FAQ.md)
466
+ 3. **查看示例代码:** [example/](../example/)
467
+ 4. **提交 Issue:** https://github.com/Lupeiwen0/beervid-app-cli/issues
468
+ 5. **联系技术支持:** support@beervid.ai
@@ -56,3 +56,9 @@ curl -X POST http://localhost:3000/api/publish/tts \
56
56
  -H "Content-Type: application/json" \
57
57
  -d '{"creatorId": "open_user_abc", "videoFileId": "vf_abc123", "productId": "prod_789", "productTitle": "Widget"}'
58
58
  ```
59
+
60
+ ## 账号关联提醒
61
+
62
+ - 如果同一达人既要做 TTS 挂车发布,又要查询视频数据,需要分别完成 TTS 和 TT 授权。
63
+ - 官方当前没有提供 `uno_id` 这类 TT/TTS 关联字段。
64
+ - 这个示例更推荐在 OAuth 回调后的 `account/info` 同步阶段持久化 `username`,并在你方数据库里用它建立 TT/TTS 关联。
@@ -182,10 +182,26 @@ app.get('/oauth/tts', async (_req, res) => {
182
182
 
183
183
  // OAuth 回调处理
184
184
  app.get('/oauth/callback', async (req, res) => {
185
- const ttAbId = req.query['ttAbId'] as string | undefined
186
- const ttsAbId = req.query['ttsAbId'] as string | undefined
185
+ const stateParam = req.query['state'] as string | undefined
187
186
 
188
- // 生产环境:① 验证 state token ② 一次性消费检查
187
+ if (!stateParam) {
188
+ res.status(400).json({ error: '缺少 state 参数' })
189
+ return
190
+ }
191
+
192
+ // 回调字段在 state JSON 内部
193
+ let stateObj: Record<string, unknown>
194
+ try {
195
+ stateObj = JSON.parse(stateParam) as Record<string, unknown>
196
+ } catch {
197
+ res.status(400).json({ error: 'state 不是合法 JSON' })
198
+ return
199
+ }
200
+
201
+ const ttAbId = stateObj['ttAbId'] as string | undefined
202
+ const ttsAbId = stateObj['ttsAbId'] as string | undefined
203
+
204
+ // 生产环境:① 验证 state 中你方追加的自定义安全字段 ② 一次性消费检查
189
205
  // 详见 docs/oauth-callback.md
190
206
 
191
207
  if (!ttAbId && !ttsAbId) {
@@ -209,6 +225,8 @@ app.get('/oauth/callback', async (req, res) => {
209
225
  openApiPost('/api/v1/open/account/info', { accountType, accountId })
210
226
  .then((info) => {
211
227
  const existing = accountStore.get(accountId) ?? {}
228
+ // 生产环境建议在这里把 username 持久化,并作为当前推荐的 TT/TTS 关联键。
229
+ // 官方没有提供 uno_id 这类可直接关联 TT/TTS 的稳定字段。
212
230
  accountStore.set(accountId, { ...existing, ...info })
213
231
  console.log(`[异步] 账号信息已同步: ${accountId}`)
214
232
  })
@@ -300,8 +318,8 @@ app.post('/api/publish/tts', async (req, res) => {
300
318
  }
301
319
 
302
320
  try {
303
- // 商品标题最多 29 字符
304
- const normalizedTitle = productTitle.slice(0, 29)
321
+ // 商品标题最多 30 字符
322
+ const normalizedTitle = productTitle.slice(0, 30)
305
323
 
306
324
  // 挂车发布(不重试——发布操作非幂等)
307
325
  const publishResult = await openApiPost<{ videoId: string }>(
@@ -52,3 +52,9 @@ npm run dev
52
52
  - `lib/beervid-client.ts` — 服务端 BEERVID API 客户端封装
53
53
  - `app/api/` — API Route Handlers
54
54
  - `app/page.tsx` — 简单首页展示 API 调用方式
55
+
56
+ ## 账号关联提醒
57
+
58
+ - TTS 账号只能用于挂车发布和商品查询,不能直接查视频数据。
59
+ - 如果同一达人还要查视频数据,需要额外完成 TT 授权。
60
+ - 官方当前没有提供 `uno_id` 这类 TT/TTS 关联字段,建议在 OAuth 回调后调用 `account/info`,并用返回的 `username` 建立本地关联。
@@ -1,25 +1,41 @@
1
1
  /**
2
- * GET /api/oauth/callback?ttAbId=xxx 或 ?ttsAbId=xxx
3
- * OAuth 回调处理
2
+ * GET /api/oauth/callback?state={"ttAbId":"xxx",...}
3
+ * OAuth 回调处理 — 回调字段在 state JSON 内部
4
4
  */
5
5
  import { NextRequest, NextResponse } from 'next/server'
6
6
  import { openApiPost } from '@/lib/beervid-client'
7
7
 
8
8
  export async function GET(request: NextRequest) {
9
- const ttAbId = request.nextUrl.searchParams.get('ttAbId')
10
- const ttsAbId = request.nextUrl.searchParams.get('ttsAbId')
9
+ const stateParam = request.nextUrl.searchParams.get('state')
11
10
 
12
- // 生产环境:① 验证 state token ② 一次性消费检查
11
+ if (!stateParam) {
12
+ return NextResponse.json({ error: '缺少 state 参数' }, { status: 400 })
13
+ }
14
+
15
+ // 回调字段在 state JSON 内部
16
+ let stateObj: Record<string, unknown>
17
+ try {
18
+ stateObj = JSON.parse(stateParam) as Record<string, unknown>
19
+ } catch {
20
+ return NextResponse.json({ error: 'state 不是合法 JSON' }, { status: 400 })
21
+ }
22
+
23
+ const ttAbId = stateObj['ttAbId'] as string | undefined
24
+ const ttsAbId = stateObj['ttsAbId'] as string | undefined
25
+
26
+ // 生产环境:① 验证 state 中你方追加的自定义安全字段 ② 一次性消费检查
13
27
  // 详见 docs/oauth-callback.md
14
28
 
15
29
  if (!ttAbId && !ttsAbId) {
16
- return NextResponse.json({ error: '缺少 ttAbId 或 ttsAbId 参数' }, { status: 400 })
30
+ return NextResponse.json({ error: 'state 中缺少 ttAbId 或 ttsAbId' }, { status: 400 })
17
31
  }
18
32
 
19
33
  const accountId = (ttAbId ?? ttsAbId)!
20
34
  const accountType = ttAbId ? 'TT' : 'TTS'
21
35
 
22
36
  // 异步拉取账号详情(不阻塞回调响应)
37
+ // 生产环境建议在这里把 username 写入数据库,并作为当前推荐的 TT/TTS 关联键。
38
+ // 官方没有提供 uno_id 这类可直接关联 TT/TTS 的稳定字段。
23
39
  openApiPost('/api/v1/open/account/info', { accountType, accountId }).catch((err) => {
24
40
  console.error('[异步] 账号信息同步失败:', (err as Error).message)
25
41
  })
@@ -8,7 +8,7 @@
8
8
  import { NextRequest, NextResponse } from 'next/server'
9
9
  import { openApiPost } from '@/lib/beervid-client'
10
10
 
11
- const MAX_PRODUCT_TITLE_LENGTH = 29
11
+ const MAX_PRODUCT_TITLE_LENGTH = 30
12
12
 
13
13
  export async function POST(request: NextRequest) {
14
14
  const body = await request.json()
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
28
28
  }
29
29
 
30
30
  try {
31
- // 商品标题最多 29 字符,超出自动截断
31
+ // 商品标题最多 30 字符,超出自动截断
32
32
  const normalizedTitle = productTitle.slice(0, MAX_PRODUCT_TITLE_LENGTH)
33
33
  const wasTruncated = normalizedTitle !== productTitle
34
34
 
@@ -49,3 +49,9 @@ npx tsx query-products.ts --creator-id open_user_abc
49
49
  | `tts-publish-flow.ts` | ⭐ TTS 完整发布流程最佳实践(含商品筛选策略) |
50
50
  | `get-oauth-url.ts` | 获取 TT/TTS OAuth 授权 URL |
51
51
  | `query-products.ts` | TTS 商品查询与分页遍历 |
52
+
53
+ ## 账号关联提醒
54
+
55
+ - TTS 账号不能直接查询视频数据。
56
+ - 如果同一达人既要跑 `tts-publish-flow.ts`,又要查视频数据,还需要额外授权 TT 账号。
57
+ - 官方当前没有提供 `uno_id` 可直接关联 TT/TTS,示例项目当前推荐使用 `account/info` 返回的 `username` 做关联。
@@ -55,7 +55,7 @@ interface ProductPageData {
55
55
  nextPageToken?: string | null
56
56
  }
57
57
 
58
- const MAX_PRODUCT_TITLE_LENGTH = 29
58
+ const MAX_PRODUCT_TITLE_LENGTH = 30
59
59
 
60
60
  // ─── 辅助函数 ───────────────────────────────────────────────────────────────
61
61