视频与预告片 API
视频接口列出电影或剧集的预告片、先导预告、片段和花絮。每条记录给出视频平台名称、视频 key、类型、是否官方、分辨率和发布日期。季与单集路径存在但不返回视频。请在你自己的代码里按语言和类型筛选。
获取电影的视频
GET / 返回挂在一部电影上的视频记录。记录只有元数据:名称、提供该视频的平台、视频在该平台上的 key、类型和几个标记。amodb 不返回视频文件。
示例打印第一条英文官方预告片,找不到时回退到任意英文预告片。
curl -s "https://api.amodb.dev/3/movie/550/videos" \
-H "Authorization: Bearer $AMODB_KEY"const url = 'https://api.amodb.dev/3/movie/550/videos';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { results } = await res.json();
const trailers = results.filter((v) => v.type === 'Trailer' && v.iso_639_1 === 'en');
const pick = trailers.find((v) => v.official) ?? trailers[0];
console.log(pick ? `${pick.name} (${pick.site}, key ${pick.key})` : 'no trailer');import os
import requests
r = requests.get(
"https://api.amodb.dev/3/movie/550/videos",
headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
timeout=10,
)
r.raise_for_status()
trailers = [v for v in r.json()["results"] if v["type"] == "Trailer" and v["iso_639_1"] == "en"]
official = [v for v in trailers if v["official"]]
pick = (official or trailers or [None])[0]
print(f"{pick['name']} ({pick['site']}, key {pick['key']})" if pick else "no trailer")<?php
$url = 'https://api.amodb.dev/3/movie/550/videos';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("amodb returned $status");
}
$trailers = array_values(array_filter(
json_decode($body, true)['results'],
fn($v) => $v['type'] === 'Trailer' && $v['iso_639_1'] === 'en'
));
$official = array_values(array_filter($trailers, fn($v) => $v['official']));
$pick = $official[0] ?? $trailers[0] ?? null;
echo $pick ? "{$pick['name']} ({$pick['site']}, key {$pick['key']})" : 'no trailer', PHP_EOL;package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
type Videos struct {
Results []struct {
Name string `json:"name"`
Key string `json:"key"`
Site string `json:"site"`
Type string `json:"type"`
Language string `json:"iso_639_1"`
Official bool `json:"official"`
} `json:"results"`
}
func main() {
url := "https://api.amodb.dev/3/movie/550/videos"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
client := &http.Client{Timeout: 10 * time.Second}
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
panic(res.Status)
}
var v Videos
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
panic(err)
}
for _, r := range v.Results {
if r.Type == "Trailer" && r.Language == "en" && r.Official {
fmt.Printf("%s (%s, key %s)\n", r.Name, r.Site, r.Key)
return
}
}
fmt.Println("no official trailer")
}参数
| 参数 | 位置 | 必填 | 说明 |
|---|---|---|---|
movie_id | 路径 | 是 | 数字形式的电影 ID,例如 550。 |
api_key | 查询 | 二选一 | 你的密钥。使用它,或使用 Authorization: Bearer 请求头。 |
language、include_video_language | 查询 | 否 | 接受但被忽略。响应始终包含该作品的全部视频。请在你的代码里按 iso_639_1 筛选。 |
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
id | integer | 电影 ID。 |
results | array | 视频记录,不按类型或日期排序。没有已知视频时为空。 |
results[].iso_639_1、results[].iso_3166_1 | string | 视频的语言和国家,例如 en 和 US。 |
results[].name | string | 视频标题,例如 #TBT Trailer。 |
results[].key | string | 视频在该平台上的 ID。 |
results[].site | string | 视频平台名称。目前始终是 YouTube。 |
results[].size | integer | 垂直分辨率。目前始终为 1080。 |
results[].type | string | Trailer、Teaser、Clip、Featurette、Behind the Scenes、Bloopers、Opening Credits 或 Recap。 |
results[].official | boolean | 由制片方或版权方发布时为 true。 |
results[].published_at | string | ISO 8601 时间戳,带或不带毫秒。 |
results[].id | string | 视频记录的 ID。与 key 相同。 |
示例响应
这里显示了电影 550 的 19 条记录中的 3 条。
{
"id": 550,
"results": [
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "Theatrical Trailer (HD Fan Remaster)",
"key": "6JnN1DmbqoU",
"site": "YouTube",
"size": 1080,
"type": "Trailer",
"official": false,
"published_at": "2015-02-26T03:19:25Z",
"id": "6JnN1DmbqoU"
},
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "#TBT Trailer",
"key": "BdJKm16Co6M",
"site": "YouTube",
"size": 1080,
"type": "Trailer",
"official": true,
"published_at": "2014-10-02T19:20:22Z",
"id": "BdJKm16Co6M"
},
{
"iso_639_1": "en",
"iso_3166_1": "US",
"name": "Mark Kermode introduces Fight Club | Film4 Interview",
"key": "tiWCNtGDGEY",
"site": "YouTube",
"size": 1080,
"type": "Featurette",
"official": true,
"published_at": "2015-05-08T15:59:05Z",
"id": "tiWCNtGDGEY"
}
]
}视频类型
type 字段告诉你视频是什么。请严格匹配,包括所示的大写字母。
| 类型 | 用途 |
|---|---|
Trailer | 主要宣传片。在详情页展示它。 |
Teaser | 在预告片之前发布的简短预告。 |
Clip | 从成片或单集中截取的场景。 |
Featurette | 讲述作品如何制作的短片。 |
Behind the Scenes | 片场画面和采访。 |
Bloopers | 剪掉的镜头和搞笑集锦。 |
Opening Credits | 剧集的片头。 |
Recap | 前几集的回顾。 |
以后可能出现其他取值,所以把未知的 type 当作一般的附加内容,不要因此报错。
挑选合适的视频
对每部作品使用同一套顺序。按顺序尝试你的语言。在同一种语言内,先官方预告片,然后任意预告片,再是先导预告,最后是片段。在同一组内按 published_at 排序:升序得到第一条预告片,降序得到最新的一条。
function pickVideo(results, langs = ['en']) {
const order = ['Trailer', 'Teaser', 'Clip'];
for (const lang of langs) {
for (const type of order) {
const group = results
.filter((v) => v.iso_639_1 === lang && v.type === type)
.sort((a, b) => Number(b.official) - Number(a.official) || Date.parse(a.published_at) - Date.parse(b.published_at));
if (group.length > 0) return group[0];
}
}
return null;
}
// Russian first, English as the fallback.
// const video = pickVideo(results, ['ru', 'en']);语言
language 和 include_video_language 不会改变响应,所以一次调用就能得到该作品的全部视频。每条记录都带有 iso_639_1 和 iso_3166_1。电影 550 有标记为 fr、en、es、pt、it、cs、pl 和 ru 的视频。如上所示在你的代码里按 iso_639_1 筛选,然后告诉用户他们将听到哪种语言。一部作品可能没有你想要语言的视频,所以请保留英文或任意语言的回退。14 种提供语言见语言。
其他视频接口
下面的路径返回相同的 id 和 results 结构。
| 方法和路径 | 返回内容 |
|---|---|
GET / | 一部剧的视频。 |
GET / | 始终是空的 results 数组。 |
GET / | 始终是空的 results 数组。 |
你也可以在电影或剧集详情调用中加 append_。追加的数据块包含 results,没有 id。剧集和季的页面分别在电视剧和季与单集中说明。
错误
| HTTP | status_code | 何时出现 |
|---|---|---|
| 401 | 7 | 密钥缺失或错误。 |
| 402 | 36 | 套餐周期已结束。 |
| 404 | 34 | 没有该 ID 的季或单集,或 ID 不是数字。 |
| 405 | 37 | 你对视频路径使用了写入方法。 |
| 429 | 25 | 超过了每分钟请求数。请等待 Retry-After 秒。 |
不存在的电影或剧集 ID 在这里不算错误:视频路径返回 200 和 "results": [],与没有视频的已知作品相同。详情路径对未知 ID 返回 404。更多见错误和速率限制。