2025, Nov 27 00:03
Как сохранить корейские названия yt-dlp на Windows при перенаправлении вывода
Разбираем, почему при перенаправлении в Windows теряется хангыль в выводе yt-dlp, и как это исправить: кодировка (UTF-8, cp949), --encoding и Python API.
Юникод в Windows по-прежнему полон ловушек, когда инструменты смешивают корейский и латиницу. Типичный сценарий: yt-dlp корректно печатает названия плейлистов в консоли, но стоит перенаправить вывод в файл или перехватить его из Python — хангыль пропадает или превращается в «заглушки». Секрет в том, чтобы понять, что делает Windows во время перенаправления, и сразу заставить yt-dlp работать в правильной кодировке.
Как воспроизвести проблему
В cmd на Windows можно вывести названия плейлиста YouTube с корейскими и латинскими символами с помощью yt-dlp. В консоли заголовки отображаются корректно при кодовой странице 949, но при перенаправлении вывода — уже нет.
yt-dlp --flat-playlist -i --print title PLySOINx0fqvYr6s8aGdqaK9j8_CAWcP5U
Перенаправьте тот же вывод в файл — и корейский исчезает:
yt-dlp --flat-playlist -i --print title PLySOINx0fqvYr6s8aGdqaK9j8_CAWcP5U > out.txt 2>&1
Перехват через Python ведёт себя так же: символы пропадают в полученной строке, даже если в консоли они видны:
import os
import subprocess
charset = "cp949"
os.environ["PYTHONIOENCODING"] = charset
cmdline = "yt-dlp --flat-playlist -i --print title PLySOINx0fqvYr6s8aGdqaK9j8_CAWcP5U"
result = subprocess.run(cmdline.split(), capture_output=True, text=True, shell=False, encoding=charset)
print((result.stdout, result.stderr))
Что происходит на самом деле
Оператор перенаправления > преобразует текст к кодовой странице консоли.
Именно на этом этапе теряются символы, если активная кодовая страница не может их представить. Минимальная демонстрация в wineconsole показывает это наглядно:
Z:\home\lmc\tmp>chcp
Active code page: 437
Z:\home\lmc\tmp>echo 철갑혹성
철갑혹성
Z:\home\lmc\tmp>echo 철갑혹성 > k.out
Z:\home\lmc\tmp>type k.out
????
Z:\home\lmc\tmp>chcp 949
Active code page: 949
Z:\home\lmc\tmp>echo 철갑혹성 > k.out
Z:\home\lmc\tmp>type k.out
철갑혹성
Когда кодовая страница не умеет сопоставлять часть символов, вы получаете либо вопросительные знаки, либо полное удаление — зависит от того, как обработчик обращается с непредставимыми знаками. Перевести все символы cp949 в cp437 невозможно. Если пытаются транслитерировать, появляются подстановки вроде вопросительных знаков; если неперекодируемые символы игнорируются — они исчезают, что и соответствует наблюдаемому поведению.
Важно и то, что ситуация не универсальна для всех платформ. В Linux Mint запись в файл в том же сценарии работала корректно; а другой терминал — например, kitty, alacritty или warp — может повлиять на отображение. Но суть проблемы Windows остаётся прежней: преобразование в кодировку консоли происходит именно во время перенаправления.
Решение: укажите yt-dlp нужную кодировку
Надёжнее всего заставить yt-dlp выводить текст в предсказуемой кодировке, которая покрывает ваши символы, и записывать этот текст напрямую, без потерь на промежуточном преобразовании. Параметр кодировки в самом yt-dlp устраняет двусмысленность. После этого всё правильно отображается в терминале, в файлах и при захвате строк — и UTF-8, и cp949 работают без проблем.
Один из вариантов — записывать перенаправленный вывод из Python, принудительно задав кодировку yt-dlp:
import subprocess
codec = "cp949"
outfile = open("out.txt", "wb")
subprocess.run(
f"yt-dlp --encoding '{codec}' --flat-playlist -i --print title PLySOINx0fqvYr6s8aGdqaK9j8_CAWcP5U".split(),
stdout=outfile,
encoding=codec,
)
После этого при кодовой странице консоли 949 можно открыть файл и увидеть корректные корейские названия:
wineconsole 2>/dev/null
Microsoft Windows 10.0.2600
Z:\home\lmc\tmp>chcp 949
Active code page: 949
Z:\home\lmc\tmp>type out.txt
Vague (feat. Hey)
새벽 한 시
천 개의 태양
Wish
...
Ещё аккуратнее — вовсе не использовать subprocess, а подключить yt-dlp как Python‑модуль, чтобы уйти от консольного перенаправления и его неявной перекодировки. Библиотека предоставляет опции, повторяющие CLI, и позволяет явно управлять кодировкой.
import yt_dlp
src_url = "https://www.youtube.com/playlist?list=PLySOINx0fqvYr6s8aGdqaK9j8_CAWcP5U"
codec = "cp949"
accum = ""
options = {
"extract_flat": True,
"playlist_items": "1-5",
"encoding": codec,
}
with yt_dlp.YoutubeDL(options) as loader:
info = loader.extract_info(src_url, download=False)
for entry in info["entries"]:
accum += f"{entry['title']}\n"
with open("out.txt", "wb") as handle:
handle.write(accum.encode(codec))
Почему это важно
Как только вывод перенаправлен, Windows применяет кодовую страницу консоли, и это преобразование может оказаться «с потерями» для многоязычного текста. Если целевая кодовая страница не поддерживает корейский, вы видите подстановки или исчезновение исходных символов. Так и выходит, что заголовки печатаются в консоли, но в файлах или захваченных строках оказываются урезанными. Контроль кодировки у источника предотвращает тихую порчу данных и делает автоматизацию надёжной.
Итоги и практические рекомендации
Если вы перенаправляете или программно перехватываете вывод yt-dlp в Windows и хотите сохранить корейский рядом с латиницей, явно задайте подходящую кодировку параметром --encoding и записывайте вывод напрямую. Использование Python API вообще избавляет от консольного перенаправления и держит единый путь данных. Где возможно, просматривайте и обрабатывайте текст в UTF-8 или cp949 — так вы избегаете «дыр» в сопоставлении, из‑за которых появляются вопросительные знаки или пропадают символы. В Linux Mint та же операция корректно писала в файл; терминалы различаются, но принцип неизменен: контролируйте кодировку от начала до конца — и символы не потеряются.