API відэа і трэйлераў

Эндпоінты відэа пералічваюць трэйлеры, тызеры, кліпы і фічарэты, прывязаныя да фільма або серыяла. Кожны запіс дае назву хоста, ключ відэа, тып, прыкмету афіцыйнасці, памер і дату публікацыі. Шляхі сезонаў і эпізодаў існуюць, але відэа не вяртаюць. Фільтруйце па мове і тыпе ў сваім кодзе.

Абноўлена Адкрыць у Markdown

Атрыманне відэа фільма

GET /3/movie/{movie_id}/videos вяртае запісы відэа, прывязаныя да аднаго фільма. Запіс уяўляе сабой толькі метаданыя: назву, хост, які аддае відэа, ключ відэа на гэтым хосце, тып і некалькі прыкмет. amodb не вяртае відэафайлы.

У прыкладзе друкуецца першы афіцыйны англійскі трэйлер, а калі яго няма, любы англійскі трэйлер.

bashjspyphpgo
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цэлы лікId фільма.
resultsмасіўЗапісы відэа, не адсартаваныя па тыпе або даце. Пусты, калі нічога невядома.
results[].iso_639_1, results[].iso_3166_1радокМова і краіна відэа, напрыклад en і US.
results[].nameрадокНазва відэа, напрыклад #TBT Trailer.
results[].keyрадокId відэа на гэтым хосце.
results[].siteрадокНазва хоста відэа. Сёння заўсёды YouTube.
results[].sizeцэлы лікВертыкальнае разрозненне. Сёння заўсёды 1080.
results[].typeрадокTrailer, Teaser, Clip, Featurette, Behind the Scenes, Bloopers, Opening Credits або Recap.
results[].officialлагічнае значэннеTrue, калі студыя або праваўладальнік апублікавалі яго.
results[].published_atрадокЧасовая пазнака ISO 8601, з мілісекундамі або без іх.
results[].idрадокId запісу відэа. Роўны key.

Прыклад адказу

Паказаны тры з 19 запісаў фільма 550.

JSON
{
  "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: па ўзрастанні дае першы трэйлер, па змяншэнні апошні.

JavaScript
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 /tv/{series_id}/videosВідэа серыяла.
GET /tv/{series_id}/season/{season_number}/videosЗаўсёды пусты масіў results.
GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/videosЗаўсёды пусты масіў results.

Таксама можна дадаць append_to_response=videos да выкліку дэталяў фільма або серыяла. Далучаны блок змяшчае results і не мае id. Старонкі серыялаў і сезонаў апісаны ў серыялы і сезоны і эпізоды.

Памылкі

HTTPstatus_codeКалі
4017Ключ адсутнічае або няправільны.
40236Тэрмін дзеяння плана скончыўся.
40434Няма сезона або эпізода з гэтым id, або id не з’яўляецца лікам.
40537Вы выкарысталі метад запісу на шляху відэа.
42925Вы перавысілі ліміт запытаў у хвіліну. Пачакайце Retry-After секунд.

Id фільма або серыяла, якога не існуе, тут не памылка: шлях відэа адказвае 200 з "results": [], гэтак жа, як і для вядомай назвы без відэа. Шлях дэталяў на невядомы id адказвае 404. Больш на старонках памылкі і ліміты запытаў.

Практычныя заўвагі

  • Захоўвайце абраныя site і key разам з назвай, а не поўны адрас, каб потым можна было змяніць прайгравальнік.
  • Спісы відэа выконваюць кэш дэталяў на edge у 6 гадзін. Кліенцкі кэш на некалькі гадзін адпавядае яму.
  • size сёння роўны 1080 для кожнага запісу, таму па ім нельга ўбачыць, які ролік лёгкі. Дазвольце прайгравальніку выбіраць якасць.
  • Не спадзявайцеся, што трэйлер заўсёды існуе. Хавайце кнопку прайгравання, калі ваша функцыя выбару вяртае null.
  • Парадак results нічога не азначае. Сартуйце ў сваім кодзе.
  • Файлы постэраў і фонавых выяў гл. на старонцы выявы. Погляд з боку выпадку выкарыстання гл. на старонцы API трэйлераў фільмаў.