Проект Subtitld

ОткрытьСохранитьZIPXMLПроект

Собственный файл Subtitld: ZIP-пакет, в начале которого лежит USF-документ с субтитрами, их переводами, говорящими и озвучкой, затем манифест всего остального внутри, картинка того места, где вы остановились, и, если попросите, видео и его звук. Один файл, который можно перенести, сохранить в резервную копию или передать, и каждая его часть читается стандартными инструментами.

Коротко

Расширение.usfx
Тип медиаapplication/x-usfx, разновидность application/zip. В системах Apple — org.subtitld.usfx.
СпецификацияЭта страница. Пакет — ZIP от PKWARE (APPNOTE.TXT); документ — USF 1.0 с элементами Subtitld.
ПакетZIP, элементы сжаты Deflate (RFC 1951) и проверяются CRC-32; Zip64 для файлов больше 2 ГиБ
Первый элементsubtitles.usf: его имя стоит с байта 30 в каждом проекте, сохраненном Subtitld
Точность времениСубтитры: миллисекунды. Озвучка: точные секунды, со столькими знаками после запятой, сколько нужно.
Кодировка текстаUTF-8, в XML и в именах элементов
ОформлениеКак в USF: курсив, полужирный, подчеркивание, зачеркивание, цвет и девять мест
ГоворящиеУ каждого имя, цвет, изображение и голос
ЯзыкиОригинал и каждый перевод, по блоку на каждый, по коду ISO 639-2 и названию
Медиа внутриОзвучка и изображения говорящих; видео, его звук, отделенные голоса и фон, а также форма волны таймлайна, если попросите

Анатомия файла

.usfx — это ZIP. Его откроет любой архиватор, если нужно, после переименования в .zip.

Tears of Steel.usfx
subtitles.usf
manifest.xml
thumbnail.png
assets/speakers/Celia.png
assets/dubs/77a03e27.wav
assets/video/Tears_of_Steel.mkv
assets/waveform.npy
assets/audio/vocals.flac
  1. 1 · Документ

    Сам проект, в USF: каждый субтитр, перевод, говорящий и озвучка. Всегда есть, всегда первым.

  2. 2 · Манифест

    Чем создан файл, где лежало видео, как был сведен звук, и тип медиа для каждого другого элемента.

  3. 3 · Картинка

    То, что файловые менеджеры показывают для проекта: кадр, на котором вы остановились, его субтитр и таймлайн в этом месте.

  4. 4 · Ресурсы

    Звук каждой озвучки и лица говорящих; видео, его звук и форма волны только по запросу.

Документ говорит, что происходит; ресурсы — это то, что он воспроизводит. Озвучка в subtitles.usf ссылается на свой клип по пути в пакете, assets/dubs/77a03e27.wav, поэтому пакет можно перенести в другую папку, на другой диск или компьютер, и он останется целым.

Элементы

Путь Что содержит Сжатие Записывается
subtitles.usf Документ: субтитры, переводы, говорящие, голоса, озвучка Deflate Всегда, первым
manifest.xml Манифест Deflate Всегда, вторым
thumbnail.png PNG-карточка проекта 512 × 384 Без сжатия Когда есть из чего сделать картинку
assets/speakers/<speaker>.png Изображение говорящего, не более 256 пикселей по стороне Deflate Если не отключить
assets/dubs/<uid>.<ext> Звук дубля озвучки, названный по ID дубля Deflate Всегда, для каждого дубля со звуком
assets/dubs/<uid>__<n>__<file> Разрезанный или растянутый кусок дубля и нетронутый источник, из которого он растянут Deflate Когда дубль разрезан или растянут
assets/video/<file> Видео Deflate По запросу
assets/waveform.npy Пики формы волны таймлайна, массив NumPy Deflate По запросу
assets/audio/original.flac Звук видео Deflate По запросу
assets/audio/vocals.flac, background.flac Звук, разделенный на голоса и остальное Deflate По запросу

Имена в assets/ состоят из букв, цифр, -, _ и .; все остальное становится _, так что Tears of Steel.mkv сохраняется как Tears_of_Steel.mkv. Буквы вне ASCII сохраняются, имя записывается в UTF-8 и помечается соответствующим образом (бит 11 заголовка ZIP), как требует APPNOTE.

Почему картинка хранится без сжатия. PNG уже сжат; Deflate отнял бы только время. Без сжатия ее байты лежат в файле ровно как PNG, и генератор миниатюр читает их, ничего не распаковывая.

Первые байты

Каждый проект начинается одинаково: локальный заголовок файла ZIP, затем имя первого элемента.

50 4B 03 04
14 00 00 00 08 00
4E 70 51 5D
64 CE 1E 0B
6F 3B 00 00 7F E2 00 00
0D 00 00 00
73 75 62 74 69 74 6C 65 73 2E 75 73 66
  1. 1 · Сигнатура

    PK\3\4, байты с 0 по 3: здесь начинается элемент ZIP.

  2. 2 · Заголовок

    Для распаковки нужна версия 2.0; флагов нет; метод 8, Deflate; время и дата в стиле MS-DOS (здесь 17 октября 2026 года, 14:02:28); CRC-32; сжатый и несжатый размеры (15 215 и 57 983 байта).

  3. 3 · Длина имени

    13, и без дополнительного поля.

  4. 4 · Имя

    subtitles.usf, с байта 30.

Имя никогда не сжимается, даже когда сжат сам элемент. Поэтому оно служит сигнатурой: ZIP, у которого с байта 30 стоит имя subtitles.usf, — это проект Subtitld. Tracker в Haiku отличает проекты от других архивов именно по этому правилу, 0.60 ("PK\003\004") [30] ("subtitles.usf" | "manifest.xml"), с приоритетом выше, чем у правила для обычного ZIP. ODF и EPUB делают то же самое с первым элементом по имени mimetype.

Видео может оказаться больше исходного предела ZIP в 4 ГиБ. Начиная с 2 ГиБ Subtitld записывает дополнительные поля и конечные записи Zip64 (APPNOTE, раздел 4.5), как и при числе элементов больше 65 535; их читают Subtitld, его обработчик миниатюр для Windows и любой современный unzip.

Манифест

<?xml version="1.0" encoding="UTF-8"?>
<manifest version="1.0">
  <format>USFX</format>
  <generator>Subtitld</generator>
  <source path="/home/ana/Videos/Tears of Steel.mkv"
          basename="Tears of Steel.mkv"/>
  <voicemix volume="0.5000"/>
  <entry path="subtitles.usf" type="application/x-usf+xml"/>
  <entry path="thumbnail.png" type="image/png"/>
  <entry path="assets/speakers/Celia.png" type="image/png"/>
  <entry path="assets/dubs/77a03e27.wav" type="audio/wav"/>
</manifest>
Элемент Что содержит
<manifest version> Версия манифеста, 1.0
<format>, <generator> USFX и то, чем записан файл: Subtitld
<source path basename> Полный путь к видео на момент сохранения проекта и одно имя файла
<voicemix volume> Положение ползунка Музыка/Голос: 0 — только фон, 0.5 — звук как есть, 1 — только голоса, а озвучка затихает вместе с фоном
<entry path type> По одному для каждого элемента, кроме самого манифеста, у каждого свой тип медиа

Типы: application/x-usf+xml, image/png, audio/wav, audio/flac, audio/mpeg, video/mp4, video/x-matroska, video/quicktime, video/webm, video/ogg и application/octet-stream для формы волны и всего остального.

Путь к видео путешествует вместе с файлом. <source path> — это место, где лежало видео на компьютере, сохранившем проект, вместе с папками и именем пользователя. Помните об этом, прежде чем делиться проектом. Если путь никуда не ведет, Subtitld ищет видео по имени в папке проекта.

Документ

subtitles.usf — это файл Universal Subtitle Format в UTF-8, такой, какой Subtitld пишет и сам по себе, с добавленным тем, что нужно проекту, в стиле самого USF: элементы и атрибуты там, где в USF их нет. Читатель USF, пропускающий то, чего не знает, прочитает субтитры.

<USFSubtitles version="1.0"
              xmlns:subtitldcc="https://subtitld.cc/ns/usf/1">
  <metadata>
    <title>Tears of Steel</title>
    <author><name>Subtitld</name></author>
    <language code="eng">English</language>
    <subtitldcc:origin share-id="Xk3pQ9aZ2bT" version="3"/>
  </metadata>
  <styles>
    <style name="Celia">
      <fontstyle color="#e5484d"/>
      <dubbing engine="edge-tts" voice="en-GB-SoniaNeural"
               rate="0" pitch="0" fit_to_subtitle="true"/>
    </style>
  </styles>
  <subtitles>
    <language code="eng">English</language>
    <subtitle start="00:00:23.000" stop="00:00:24.500">
      <text speaker="Celia" style="Celia">You're a jerk, Thom.</text>
      <dubbing uid="77a03e27" engine="edge-tts"
               voice="en-GB-SoniaNeural" rate="0" pitch="0"
               path="assets/dubs/77a03e27.wav"
               start="23.0" end="24.5"/>
    </subtitle>
  </subtitles>
  <subtitles>
    <language code="por">Portuguese (Brazil)</language>
    <subtitle start="00:00:23.000" stop="00:00:24.500">
      <text speaker="Celia" style="Celia">Você é um idiota, Thom.</text>
    </subtitle>
  </subtitles>
</USFSubtitles>

Что Subtitld добавляет к USF

Где Элемент или атрибут Что содержит
<metadata> <subtitldcc:origin share-id version> Субтитры на subtitld.cc, из которых вырос проект, чтобы изменения можно было опубликовать как их следующую версию. В собственном пространстве имен, https://subtitld.cc/ns/usf/1, записывается, только когда есть.
<styles> <style name> По одному на каждого говорящего, названный его именем. Без стиля Default, который изменил бы оформление всех субтитров в плеере.
<style> <fontstyle color> Цвет говорящего, #RRGGBB
<style> <dubbing engine voice rate pitch fit_to_subtitle> Голос говорящего: движок, голос, скорость и высота от −100 до 100, и подгоняется ли озвучка под длительность субтитра
<text> speaker, style Кто это говорит, и его стиль
<text> alignment Одно из девяти мест USF, от TopLeft до BottomRight; отсутствует для низа по центру
<subtitle> <dubbing> Дубль озвучки субтитра, по элементу на каждый
<dubbing> uid engine voice rate pitch ID дубля и голос, которым он сделан
<dubbing> path, raw_path Его звук в пакете и источник, из которого сделан растянутый дубль
<dubbing> start, end Где он звучит на таймлайне, в секундах
<dubbing> <subclip type path raw_path start end offset rate> Куски дубля, который разрезали или растянули

В обычном .usf изображения говорящих и звук озвучки могут храниться внутри XML, в base64 в <avatar> и <data>. .usfx так никогда не делает: это отдельные элементы, на четверть меньше, чем в base64, и читаются они без разбора XML.

Время

start и stop субтитра — это время USF, округленное до ближайшей миллисекунды. Время озвучки — простые секунды, записанные полностью, 18.01579117916244: кратчайшая десятичная запись, которая читается обратно как то же 64-битное число, поэтому клип, поставленный перетаскиванием, возвращается ровно туда, где был.

Старые версии Subtitld записывали время на миллисекунду раньше, а начало в нуле — как 23:59:59.999. Subtitld читает это значение как ноль, а миллисекунду оставляет как есть.

Дубли и подклипы

У субтитра может быть несколько дублей. Первый <dubbing> — тот, что звучит; остальные — альтернативы, молчащие, пока вы не выберете одну, и тогда она переходит в начало.

Дубль, который разрезали или растянули, хранит список <subclip>, расставленных как клипы в аудиоредакторе:

Атрибут Значение
start, end Часть исходного файла, которая звучит, в секундах от начала файла
offset Где эта часть начинается, в секундах от start дубля
rate Скорость, до которой ее растянули: 20 — это 120 %
path, raw_path Звук, который играет, и нетронутый звук, из которого его растянули

Подклип звучит с start дубля плюс его offset, в течение end минус start секунд. Промежутки — тишина; наложения смешиваются. Источники никогда не меняются, поэтому любое разрезание и растяжение можно отменить, а растяжение всегда делается заново из raw_path, а не из растяжения растяжения.

Переводы

У каждого языка свой блок <subtitles>, с кодом ISO 639-2 и, в элементе, названием языка, которое отличает бразильский португальский от португальского Португалии. Каждый блок содержит все субтитры с теми же временами; озвучка есть только в первом. Subtitld сопоставляет перевод с субтитром по времени начала или с тем, с которым он больше всего перекрывается, так что блокам, записанным другими программами, не обязательно совпадать точно.

Открытие проекта

Большие проекты открываются сразу: Subtitld сначала читает то, что нужно редактору, а остальное — пока вы работаете.

До появления редактора
  • subtitles.usf, ради субтитров, говорящих и голосов
  • manifest.xml, ради видео и сведения
  • assets/speakers/, лица, декодируемые вне основного потока
  • Вложенное видео, распакованное один раз
Пока вы работаете
  • Озвучка, первой, чтобы ее можно было воспроизвести
  • Затем форма волны
  • Разделенный звук, последним

Каждая озвучка на таймлайне заштрихована, пока не придет ее звук, а потом воспроизводится.

Элементы распаковываются в собственные папки Subtitld, никогда не рядом с проектом: документ, лица и озвучка — в папку кэша, названную по MD5 пути проекта. То, что приходит во время работы, поступает блоками по 1 МиБ во временный файл, который по завершении переименовывается на место, так что сбой на полпути не оставляет ничего записанного наполовину. При следующем открытии того же проекта уже лежащий там файл используется снова, только если его размер в точности равен размеру элемента; иначе он распаковывается заново.

Видео ищется в таком порядке:

  1. видео внутри пакета, в assets/video/;
  2. путь в <source path>, если он еще существует;
  3. файл с именем из <source basename> в папке проекта;
  4. иначе Subtitld просит его указать.

Файл, который не является ZIP, обрезан или не проходит проверку CRC, ничего не открывает: Subtitld сообщает об этом и убирает его из списка недавних. Старые проекты тоже открываются: без манифеста или с USF под другим именем в корне ZIP.

Сохранение проекта

Сохранить никогда не подвергает риску проект, который у вас есть.

  1. Снимок. Проект копируется в том виде, в каком он был в момент сохранения, так что можно продолжать редактировать, пока он записывается. Сохранения, автосохранения и резервные копии ждут своей очереди: записывает только одно за раз.
  2. Новый файл. Пакет записывается в <project>.usfx.tmp рядом с проектом.
  3. Ничего не пропадает. Озвучка, чьего звука еще нет в кэше, потому что он еще поступает или был очищен, копируется из файла, который вот-вот будет заменен. Проект, сохраненный без видео, сохраняет прежнюю картинку.
  4. Проверено. Новый файл открывается снова, и CRC-32 каждого элемента сверяется.
  5. Замена. Только тогда он заменяет проект, одним переименованием (os.replace): под именем проекта никогда не лежит половина проекта.

Если какой-либо шаг не удался, временный файл удаляется, на диске остается прежний проект, а ваши правки по-прежнему открыты в Subtitld. Пока озвучка проекта еще поступает, Сохранить ее дожидается.

Что попадает внутрь

Общие настройки, затем USFX, определяют, что еще несет проект, для каждого сохраняемого проекта:

  • Портреты говорящихЛица говорящих. Включено.
  • Кэш формы волны на таймлайнеФорма волны, чтобы проект открывался на другом компьютере без повторного расчета. Выключено.
  • Исходная звуковая дорожкаЗвук видео, в FLAC. Выключено.
  • Обработанный звук (голос + фон)Звук, разделенный на голоса и остальное, в FLAC, чтобы не запускать разделение заново. Выключено.
  • Исходный видеофайлСамо видео: один файл со всем, размером с видео и больше. Выключено.

Каждый попадает внутрь, когда Subtitld есть что положить: разделенный звук, например, только после того, как разделение выполнено. Субтитры, переводы, говорящие, голоса и вся озвучка внутри всегда. Deflate уменьшает WAV озвучки примерно на шестую часть; видео и FLAC почти не сжимаются.

Автосохранение и резервные копии

  • Автоматически сохранять файл проектаЗаписывает сам ваш .usfx, как Сохранить, тем же безопасным способом. Для проекта, сохраненного как USFX.
  • Автоматические резервные копииПолный .usfx в папке резервных копий Subtitld, отдельно от вашего файла, с именем <project>_<YYYYMMDDHHMMSS>.usfx, когда есть изменения, которые стоит сохранить. Сверх Хранить не более, 20, если не выбрать иное, самые старые удаляются.

В файловых менеджерах

Миниатюра — это карточка в стиле Subtitld: кадр видео, на котором остановился проект, субтитр на нем, а под ним двенадцать секунд таймлайна вокруг курсора воспроизведения, форма волны и субтитры в цветах их говорящих. 4:3 при 512 × 384, поэтому она лучше заполняет квадратную ячейку файлового менеджера, чем широкий кадр. Без видео вместо кадра стоит знак Subtitld.

Система Тип Что это дает
Linux application/x-usfx в shared-mime-info, разновидность application/zip, распознается по *.usfx Собственный значок; с пакетом из AUR — миниатюры от subtitld-thumbnailer, генератора миниатюр freedesktop.org
Windows Тип файла в установщике и в пакете MSIX Значок; поставщик миниатюр оболочки (UsfxThumbnail.dll, IThumbnailProvider), который сам читает центральный каталог ZIP, включая Zip64, и декодирует PNG через WIC в размере, который просит Проводник
macOS Тип org.subtitld.usfx, соответствующий public.zip-archive Собственный значок
Haiku application/x-usfx, с правилом распознавания, приведенным выше Значок, и Tracker, отличающий проект от ZIP

По двойному щелчку проект открывается в Subtitld во всех четырех. Оба генератора миниатюр читают только thumbnail.png, отвергают файл больше 8 МиБ и не принимают ничего, что не начинается с сигнатуры PNG, 89 50 4E 47 0D 0A 1A 0A. Генератор для Windows принимает его только без сжатия, как его записывает Subtitld. Генератор для Linux использует только стандартную библиотеку Python, поскольку файловые менеджеры запускают генераторы миниатюр в песочнице и по многу сразу.

Как прочитать .usfx самостоятельно

Ничто в проекте не принадлежит одному лишь Subtitld. Чтобы заглянуть внутрь:

unzip -l "Tears of Steel.usfx"
unzip -p "Tears of Steel.usfx" manifest.xml

Чтобы прочитать его субтитры на всех языках стандартной библиотекой Python:

import zipfile
import xml.etree.ElementTree as ET

def text_of(element):
    """A <text>'s words, <br/> as a line break."""
    parts = [element.text or '']
    for child in element:
        parts.append('\n' if child.tag == 'br' else text_of(child))
        parts.append(child.tail or '')
    return ''.join(parts)

with zipfile.ZipFile('Tears of Steel.usfx') as usfx:
    usf = ET.fromstring(usfx.read('subtitles.usf'))

for block in usf.iter('subtitles'):
    language = block.find('language')
    if language is not None:
        print('#', language.get('code'), language.text)
    for subtitle in block.iter('subtitle'):
        text = subtitle.find('text')
        print(subtitle.get('start'), subtitle.get('stop'),
              text.get('speaker'), text_of(text))

Чужой проект разбирайте с помощью defusedxml вместо xml.etree, как и любой XML, который вы писали не сами.

Как создать свой

Самый маленький проект, который откроет Subtitld, — это ZIP с одним subtitles.usf. Без манифеста Subtitld попросит указать видео. Чтобы сделать проект, который узнают и файловые менеджеры, повторяйте то, что пишет Subtitld:

  • сначала subtitles.usf, затем manifest.xml;
  • каждый элемент сжат Deflate, кроме thumbnail.png, хранимого без сжатия;
  • озвучка в assets/dubs/, на которую документ ссылается по пути в пакете;
  • везде UTF-8.

Subtitld сохраняет то, что знает. При сохранении записываются элементы, описанные на этой странице, и документ, построенный из того, что Subtitld понял в старом. Файл, добавленный в пакет другой программой, или собственный элемент в USF пропадает, как только Subtitld сохранит проект. Храните свои данные рядом.

Сравнение

USFX устроен так же, как пакеты документов офисных пакетов и электронных книг: ZIP, основной документ в XML, опись и медиа рядом.

ODF (.odt) EPUB Office Open XML (.docx) USFX
Стандарт OASIS ODF 1.3, часть 2 W3C EPUB 3.3, его OCF ECMA-376 часть 2, OPC Эта страница
Как программа его узнает Первый элемент mimetype, без сжатия Первый элемент mimetype, без сжатия: application/epub+zip [Content_Types].xml Имя первого элемента, subtitles.usf, с байта 30
Опись META-INF/manifest.xml, тип для каждого файла META-INF/container.xml, затем документ пакета [Content_Types].xml и _rels/ manifest.xml, тип для каждого элемента
Основной документ content.xml Документ пакета и его spine word/document.xml subtitles.usf
Медиа Pictures/ Где угодно в пакете word/media/ assets/
Превью Thumbnails/thumbnail.png Изображение обложки Необязательная часть с миниатюрой thumbnail.png, без сжатия

Основной документ — самостоятельный открытый формат: извлеките subtitles.usf из .usfx, и это будет файл USF, формат с публичной спецификацией с 2002 года.

Любопытное

30

Байт, с которого начинается имя первого элемента каждого проекта, и то, по чему Haiku отличает проект Subtitld от любого другого ZIP.

512 × 384

Размер картинки проекта: 4:3, потому что файловые менеджеры показывают файлы в квадратах.

26.10

Выпуск, который дал .usfx собственный значок в Linux, Windows, macOS и Haiku, а также картинку в Проводнике Windows и файловых менеджерах Linux.

Похожие форматы

Начните проект

Откройте видео в Subtitld, сделайте к нему субтитры и сохраните: это и есть .usfx.

Скачать Subtitld