Скачивание видео из соцсетей на Go
Клиент на Go — запрос с одним заголовком и типизированный decode. Руководство добавляет дисциплину вокруг: дедлайн через context, чтобы медленный источник не повесил горутину, структуру, которая делает код ошибки полем, а не поиском по строке, и потоковую запись файла через io.Copy вместо чтения в память.
Обновлено
Сначала типы
Структура с Success, Medias и указателем Error делает код ошибки полем, а не поиском по строке. Держите тип локальным и маленьким — новое необязательное поле в ответе не сломает decode, который его игнорирует.
Gotype Media struct {
Type string `json:"type"`
URL string `json:"url"`
}
type Resolved struct {
Success bool `json:"success"`
Medias []Media `json:"medias"`
Error *struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}Запрос
http.NewRequestWithContext несёт дедлайн; url.QueryEscape кодирует ссылку. Один заголовок, один decode. Больше ничего с вашей стороны — ни cookie, ни сессии, ни браузера.
Gofunc resolve(ctx context.Context, link string) (*Resolved, error) {
u := "https://api.saveapi.org/v1/download?url=" + url.QueryEscape(link)
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
req.Header.Set("Authorization", "Bearer sk_live_xxxx")
res, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var out Resolved
return &out, json.NewDecoder(res.Body).Decode(&out)
}Пишите файл через io.Copy
URL медиа указывает прямо на CDN платформы. io.Copy из тела ответа в файл держит память ровной при любом размере; API никогда не проксирует байты.
Goctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
data, err := resolve(ctx, "https://www.instagram.com/reel/ABC123/")
if err != nil || !data.Success {
log.Fatal(err, data.Error.Code)
}
res, _ := http.Get(data.Medias[0].URL) // to'g'ridan-to'g'ri CDN
defer res.Body.Close()
f, _ := os.Create("video.mp4")
defer f.Close()
io.Copy(f, res.Body) // oqim, xotiraga emasПовторяйте только то, что повтор исправляет
UPSTREAM_TIMEOUT и UPSTREAM_ERROR заслуживают второй попытки и ничего не стоят. PRIVATE_CONTENT и MEDIA_NOT_FOUND финальны и стоят 0.1 кредита каждый раз — цикл повторов на них лишь тратит кредиты на тот же ответ. Держите набор повторяемых в одном месте.
Читайте заголовки, которые уже есть
Каждый ответ несёт X-RateLimit-Limit, X-RateLimit-Remaining и на платных ключах X-Credits-Remaining. Этого достаточно, чтобы притормозить до троттлинга без отдельного запроса баланса.
Вопросы перед началом
- Есть официальный Go SDK?
- Нет. Типизированная структура и запрос из этого руководства и есть SDK; пакет добавил бы зависимость ради восьми строк.
- Как обрабатывать formats[]?
- Добавьте поле Formats []Format в структуру для VK и Rutube; на других платформах поле просто отсутствует и остаётся пустым.
- Можно разрешать много ссылок параллельно?
- Да, в пределах поминутного лимита ключа. Семафор размером с лимит и заголовок X-RateLimit-Remaining уберегут от троттлинга.
Платформы, использованные здесь
Другие руководства
Запустите это руководство со своим ключом
Ключ за минуту. 1 000 бесплатных кредитов, без карты и без срока.