«Качалка видео для Windows и Mac: почему TikTok не пускал собранную программу, а QuickTime принимал видео за музыку»

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Качалка видео для Windows и Mac: почему TikTok не пускал собранную программу, а QuickTime принимал видео за музыку

Вставляешь ссылку на видео с YouTube, TikTok, VK или Instagram, выбираешь 1080 p, 720 p или 480 p и жмёшь «Скачать». Через несколько секунд на Рабочем столе лежит mp4, который открывается в QuickTime, на айфоне и в любом плеере Windows. Пока идёт загрузка, по пиксельному офису бегает человечек и складывает в папку листки.

Это Качалка — бесплатная программа с открытым кодом. Никаких аккаунтов, рекламы и водяных знаков. Ниже — из чего она собрана и два бага, на которые я потратил больше всего времени: оба проявлялись только в собранной программе и ни разу при запуске из кода.

Давно хотел делать бесплатно для людей, время пришло.

Из чего собрано

  • yt‑dlp делает всю тяжёлую работу: достаёт видео с сотен сайтов.

  • FFmpeg склеивает видео со звуком. Он едет внутри программы через пакет imageio-ffmpeg, так что ставить ничего не нужно.

  • CustomTkinter рисует окно: тёмная тема, фиолетовые кнопки.

  • PyInstaller собирает Kachalka.exe для Windows и Kachalka.app для Mac.

  • GitHub Actions собирает обе версии по тегу. У меня нет компьютера с Windows, так что exe я ни разу не собирал сам.

«Код писал вместе с Claude Code; идея, решения и проверка — мои».

Почему H.264, а не «лучшее качество»

Первое желание — качать максимум. Но YouTube отдаёт высокие разрешения в VP9 и AV1, а QuickTime и айфон такие файлы часто не открывают. Пользователь скачал видео, кликнул — а оно не играет. Поэтому Качалка всегда просит H.264 и звук AAC:

"format": "bv*+ba/b",
"format_sort": ["vcodec:h264", f"res:{height}", "acodec:m4a"],
"merge_output_format": "mp4",

Тонкость с res: yt‑dlp считает разрешение по меньшей стороне. Поэтому вертикальный TikTok 1080×1920 честно считается 1080 p и не отсекается фильтром «не больше 1080». Если бы я фильтровал по height, вертикальные видео скачивались бы в плохом качестве.

Цена решения — нет 4K: в H.264 его практически никто не отдаёт. Перекодировать 4K на компьютере пользователя — минуты ожидания, для простой качалки это лишнее.

Баг 1: TikTok пускает Python, но не пускает собранную программу

Из кода всё качалось. Собранная программа на той же ссылке падала:

ERROR: [TikTok] 7698495498537143604: Unexpected response from webpage request

Я последовательно исключал причины:

  • Сеть и VPN. VPN работает на весь компьютер, системного прокси нет. И скрипт, и программа ходят в сеть одинаково.

  • Окружение. Программа, запущенная из терминала, а не из Finder, падала так же.

  • Версия yt‑dlp. В логе сборки GitHub та же версия, что у меня, 2026.08.19.

  • Состав библиотек. Почти совпадал.

Остался Python. Локально у меня одна сборка Python, на GitHub — другая, с другими настройками TLS. По всей видимости, TikTok смотрит на «почерк» TLS‑соединения и одной сборке отдаёт нормальную страницу, а другой — заглушку. yt‑dlp, кстати, сам об этом предупреждал, а я не обратил внимания:

WARNING: [TikTok] The extractor is attempting impersonation,
but no impersonate target is available.

Решение — пакет curl_cffi: он умеет подключаться с отпечатком настоящего Chrome или Safari. Достаточно поставить yt‑dlp с нужным дополнением и не забыть положить пакет в сборку:

# requirements.txt
yt-dlp[default,curl-cffi]

# build.py
"--collect-all=curl_cffi",

Главный урок: проверять надо собранную программу, а не код. Локально ошибка не воспроизводилась ни разу. Я собрал пробную версию в отдельной ветке, скачал её из GitHub Actions и только после этого выпустил исправление.

Баг 2: видео из TikTok открывается как музыка

TikTok начал качаться, но в Finder вместо превью у файла была нота, а QuickTime видел в нём только звук. При этом ffprobe показывал нормальный H.264 1080×1080, а ffmpeg декодировал кадры без единой ошибки.

Странным было одно поле — масштаб времени видеодорожки:

stream|codec_type=video|time_base=1/5995319

Почти шесть миллионов делений в секунду. Я спросил у видеодвижка macOS напрямую, что он видит в файле:

asset = AVFoundation.AVURLAsset.URLAssetWithURL_options_(url, None)
len(asset.tracksWithMediaType_(AVFoundation.AVMediaTypeVideo))
# исходный файл — 0 видеодорожек
# после переупаковки — 1

Ноль. Для macOS видео в этом файле просто не существовало. Лечится переупаковкой без перекодирования: качество то же, работы на пару секунд.

ffmpeg -i in.mp4 -map 0 -c copy -video_track_timescale 90000 -movflags +faststart out.mp4

Теперь Качалка делает это после каждой загрузки. На Windows ffmpeg запускается с флагом CREATE_NO_WINDOW, иначе на секунду мелькает чёрное окно консоли.

Плавный прогресс, когда файлов два

YouTube отдаёт видео и звук отдельно, и прогресс yt‑dlp идёт дважды от 0 до 100%. Пользователь видит, как полоска доходит до конца и прыгает в ноль. Поэтому перед загрузкой Качалка смотрит размеры обеих частей и считает общий прогресс с весами. Полоска не прыгает к цели, а плавно догоняет её — каждые 16 мс проходит 12% оставшегося пути. Последние 3% оставлены на склейку.

Человечек в офисе

Гифка нарисована кодом на Pillow, без готовых ассетов. Холст 160×80 «пикселей» увеличивается в три раза без сглаживания. Офис — это кусок шириной 96 пикселей, который едет на 2 пикселя за кадр: за 48 кадров он проезжает ровно свою ширину, поэтому петля бесшовная. 48 кадров по 40 мс дают 25 кадров в секунду.

Ещё одна мелочь для Retina: CustomTkinter сам масштабирует картинки и размывает пиксель‑арт. Поэтому кадры заранее увеличиваются в два раза «по пикселям», и масштабировать окну уже нечего.

Сборка для двух систем без Windows

Одна матрица GitHub Actions: windows-latest собирает однофайловый exe, macos-latest — .app в zip. По тегу v* оба файла уходят в релиз, а к релизу прикладывается подпись происхождения. Любой может проверить, что файл собран из этого репозитория:

gh attestation verify Kachalka-Windows.exe --owner kozliq

Две вещи, которые пришлось объяснять в README:

  • Программа без платной подписи. Windows показывает «Система Windows защитила ваш компьютер», macOS — «не удаётся проверить разработчика». Это обходится за один шаг, но предупредить нужно.

  • Блокировки. Многие обходят их VPN‑расширением или DNS в настройках браузера. Программа настроек браузера не видит, и YouTube для неё недоступен. Поэтому сырые ошибки yt‑dlp переводятся на человеческий язык: вместо getaddrinfo failed Качалка пишет «Нет связи с сайтом — похоже, он заблокирован у провайдера» и советует включить VPN для всего компьютера.

Что дальше

В планах значок в строке меню Mac: нажал, вставил ссылку, скачал — без большого окна.

Код и готовые файлы для Windows и Mac: github.com/kozliq/kachalka

Если что‑то не качается — заведите issue со ссылкой, разберусь.

Источник: https://habr.com/ru/articles/1098826/


Интересные статьи

Интересные статьи

Итак, в прошлой части мы остановились на мысли, что современный iPhone имеет смысл рассматривать уже не как устройство, в котором где-то лежит некий суперсекретный ключ, а как довольно сложную машину ...
Новое исследование Фонда электронных рубежей (EFF) показало, что некоторые Android‑приложения непреднамеренно передают данные о местоположении своих пользователей третьим сторонам, включая р...
Всем привет, случалось такое, что вам надо поставить кучу агентов битрикса на крон, а потом сидеть и разбираться - сколько они отрабатывают, отрабатывают ли вообще, когда падают или зависают? Ну конеч...
Разработчики часто встречаются с непредвиденными сложностями, причем иногда крайне непросто найти причину. На одном из проектов мы столкнулись с серьезной проблемой, которую не смогли сразу решить даж...
Эта публикация написана после неоднократных обращений как клиентов, так и (к горести моей) партнеров. Темы обращений были разные, но причиной в итоге оказывался один и тот же сценарий, реализу...