API за видеа и трейлъри

Ендпойнтите за видеа изброяват трейлърите, тийзърите, клиповете и featurette, прикачени към филм или сериал. Всеки запис дава име на хост, ключ на видеото, тип, флаг за официалност, размер и дата на публикуване. Пътищата за сезон и епизод съществуват, но не връщат видеа. Филтрирайте по език и тип във вашия код.

Обновено Отвори като 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": [], както за познато заглавие без видеа. Пътят за детайли отговаря с 404 за непознато id. Повече на страниците грешки и лимити на заявките.

Практически бележки

  • Пазете избраните site и key със заглавието, а не пълен адрес, за да можете да смените плейъра по-късно.
  • Списъците с видеа следват кеша на детайлите от 6 часа на edge. Клиентски кеш от няколко часа му съответства.
  • size е 1080 за всеки запис днес, така че не ви казва кой клип е лек. Оставете плейъра да избере качеството.
  • Не разчитайте, че трейлър съществува. Скрийте бутона за пускане, когато функцията ви за избор върне null.
  • Редът на results не носи значение. Сортирайте във вашия код.
  • За файловете с постери и фонови изображения вижте изображения. За гледната точка на случая на употреба вижте API за трейлъри на филми.