Пережимает lossless-аудио в минимальный по размеру формат без потерь: полным перебором всех поддерживаемых форматов и уровней сжатия, с проверкой результата и переносом тегов.
Из всех кандидатов выбирается файл минимального суммарного размера (аудио + теги). Победитель валидируется побайтово и заменяет исходный файл. Аудио и теги сохраняются без потерь.
Примеры экономии сильно зависят от контента: на обычной музыке в среднем выигрывает OptimFROG или TAK, на шумоподобном материале (студийный шум, эффекты) часто побеждает Monkey's Audio. Оценка по вашей коллекции —
llao.exe stats.
-
Скачайте последний релиз
llao-v<версия>-win64.zipсо страницы Releases и распакуйте в любую папку (установка не требуется). В архиве уже есть все кодеки — интернет при работе не нужен. -
Запустите из командной строки:
llao.exe tools llao.exe optimize "D:\Music" --jobs=8
tools— один раз проверит/скачает утилиты кодеков (при скачивании сверяются контрольные суммы).optimize— пережмёт все аудиофайлы в папке рекурсивно.На Linux (под wine) для
llao.exeпредусмотрена обёрткаllao, которая обеспечивает всё, чего wine не даёт из коробки, не требуя правокllao.exe:- Синглтон демона. Именованный мьютекс
Local\llao-singletonв wine существует в рамках одного wineserver (= одногоWINEPREFIX), поэтому все запуски идут в один фиксированный префикс (~/.llao-wine, переопределяется черезLLAO_WINEPREFIXилиWINEPREFIX) — вторая копияserveотвергается, как в Windows. - Инициализация префикса. Свежий префикс прогревается через
wineboot -u(как в CI проекта). - Шум отладчика подавляется (
WINEDEBUG=-all, как в тестах проекта), stderr wine уходит в${LLAO_LOG:-/tmp/llao-wine.log}. - Ширина статус-бара определяется через
stty/tputи передаётся черезLLAO_STATUS_SIZE(GetConsoleScreenBufferInfoв wine падает).
./llao tools ./llao optimize "/media/Music" --jobs=8 ./llao serveЕсли бит исполняемости не сохранился (например, после распаковки zip) —
sh llao .... - Синглтон демона. Именованный мьютекс
- Никаких потерь. Аудио переносится побайтово (декод → эталонный PCM → кодирование → проверка декода против эталона). Теги переносятся полностью: каждый формат тегов хранится отдельно и либо встраивается в целевой формат, либо выносится в ZIP-sidecar рядом с файлом.
- Полный перебор. Покрываются все форматы и все варианты сжатия; для каждого файла перебор
идёт в отдельном процессе параллельно (
--jobs). - Самодостаточность. Консольные утилиты кодеков скачиваются автоматически (с проверкой
SHA-256) и складываются в
bin/<id>/; в релизном архиве они уже есть. - Windows-native. Единый исполняемый файл
llao.exe(C++17, без установки и внешних библиотек). На Linux работает подwine(обёрткаllao) или нативно (make TARGET=linux). Все функции — CLI и headless-сервер — в одном бинарнике. - Умный порядок перебора. Внутри накапливается статистика (формат, вариант, степень сжатия,
тип контента); наиболее вероятные победители перебираются первыми. Таблицу показывает
llao.exe stats. - Lossy-входы по умолчанию пропускаются (mp3/aac и пр. пережимать в lossless бессмысленно);
обработка — только с флагом
--allow-lossy. - Контроль устаревания конфигов. При скачивании утилиты её вывод
--helpсверяется с ожиданиями конфига; при расхождении выдаётся предупреждение. - Журнал прогона. С
--debugкаждое событие (запуск, файлы, кандидаты, ошибки) пишется вruns/*.jsonl— удобно для анализа победителей и разбора сбоев. - Демон и веб-UI. Подкоманда
llao serve— headless-процесс с HTTP-API и веб-интерфейсом: очередь можно пополнять, переупорядочивать, ставить на паузу и перезапускать файлы на лету, не занимая терминал (раздел «Демон и веб-UI»).
| id | Формат | Расширение | Утилита | Примечание |
|---|---|---|---|---|
flac |
FLAC | .flac |
flac.exe |
уровни -0..-8, встроенный MD5 |
wavpack |
WavPack | .wv |
wavpack.exe |
-h/-hh + -x0..-x6, MD5 |
monkeys_audio |
Monkey's Audio | .ape |
mac.exe |
уровни -c1000..-c5000 |
alac |
Apple Lossless | .m4a |
ffmpeg.exe |
без уровней |
tta |
True Audio | .tta |
ffmpeg.exe |
без уровней |
tak |
TAK | .tak |
takc.exe |
-p0..-p4 + уровни E/M (-p4m), CRC+MD5 |
optimfrog |
OptimFROG | .ofr |
ofr.exe |
пресеты 0..10 + max, MD5 |
la |
LA | .la |
la.exe |
только 16 бит, только ID3v1 |
mpeg4_als |
MPEG-4 ALS | .m4a |
ffmpeg.exe |
выключен (кодер удалён из новых ffmpeg) |
ffmpeg-форматы (alac/tta/mpeg4_als) делят одну общую сборку bin/ffmpeg/. Полный список
параметров — llao.exe variants.
llao.exe check-formats # валидация конфигурации форматов
llao.exe tools [fmt_id ...] [--no-download] # статус/скачивание утилит в bin/<id>/
llao.exe optimize <файл|папка> [--jobs=N|M.F] # перебор форматов/параметров (рекурсивно)
[--formats flac,wavpack] # ограничить набор форматов
[--report=<файл|папка>] # итоговый отчёт (или каталог для него)
[--no-download] [--dry-run] # без скачивания / без замены файлов
[--allow-lossy] # обрабатывать и lossy-входы (mp3, aac, …)
[--verify=all|winner|none] # режим проверки кандидатов (по умолчанию all)
[--ignore-errors] # ошибки файлов — помечать skip, не прерывать прогон
[--tmp=<path>] # путь к временной папке (по умолчанию рядом с бинарником)
[--debug] [--no-stats] # журнал runs/*.jsonl / без накопления stats.json
llao.exe restore <файл|папка> [--jobs=N|M.F] # обратная оптимизация: вернуть в целевой
[--to=flac] # формат (по умолчанию FLAC), теги возвращаются
[--variant=<id>] [--no-download] [--allow-lossy]
llao.exe help <fmt_id> -- <аргументы> # запустить утилиту кодека (--help и т. п.)
llao.exe serve [опции] # headless-движок с HTTP-API и веб-UI
llao.exe stats # показать накопленную статистику
llao.exe variants # список форматов и вариантов сжатия
--jobs=N — точное число параллельных процессов; --jobs=M.F — множитель числа
доступных ядер (например, --jobs=1.5 на 16 ядрах даст 24 процесса).
По умолчанию --jobs=2.0, т.е. вдвое больше ядер. Число одновременно запущенных
процессов дополнительно ограничивается свободным местом на tmp-диске и доступной
памятью (окно адаптируется под размер файлов).
--verify управляет проверкой кандидатов:
all(по умолчанию) — каждый кандидат проверяется builtin-проверкой формата (flac -tи т. п.), декодом и побитовым сравнением PCM с эталоном;winner— при отборе кандидаты не проверяются, полностью проверяется только победитель (лучший по размеру), перед заменой файла. Быстрее, но ошибки выявляются позже, только у одного варианта;none— никакой проверки, замена сразу. Максимальная скорость, риск повреждённых файлов — на пользователе.
Ошибка любого файла (битый вход, сбой вариантов, недоступная утилита, не прошедший
проверку победитель) по умолчанию прерывает прогон с подробным отчётом: активные
процессы (кодеры/декодеры в других потоках) завершаются немедленно, не дожидаясь их
окончания. С флагом --ignore-errors такие файлы помечаются skip (исходник не
заменяется), а прогон продолжается; --ignore-errors не влияет на restore.
Вывод локализуется через каталоги lang/<код>.json. Язык выбирается в порядке приоритета:
- Флаг
--lang=ru|en(в любом месте командной строки); - переменная окружения
LLAO_LANG=ru|en; - поле
"language"вllao.jsonрядом сllao.exe("auto"по умолчанию); - автоопределение (
LANG, затем язык пользователя Windows).
Пример: в файле llao.json рядом с llao.exe:
{ "language": "ru" }Подкоманда llao serve запускает headless-движок без консольного вывода;
управление — через HTTP-API и веб-интерфейс. Можно добавлять файлы и папки
в уже работающую очередь, переставлять их, перезапускать, чистить
завершённые — терминал не нужен. Бинарник один: llao.exe / llao-linux.
llao serve [опции]
Опции сессии (дефолты оптимизации):
--jobs N|M.F— число потоков или множитель ядер (по умолчанию 2.0);--verify all|winner|none— режим проверки кандидатов (по умолчанию winner);--dry-run— не записывать результат;--no-download— не скачивать кодеки (стартовый гейт только проверяет);--no-stats— не накапливатьstats.json;--debug— журналruns/*.jsonlи отладка;--report PATH— итоговый отчёт при остановке демона (файл или каталог);--restore-to ID— целевой формат режима восстановления (по умолчаниюflac; id изformats/*.json— проверяется при старте).
Опции сервера:
--bind ADDR— адрес прослушивания (по умолчанию0.0.0.0— все интерфейсы, сервис доступен с других компьютеров локальной сети);--port N— порт (по умолчанию18180);0= свободный;--token HEX— явный токен доступа (иначе генерируется и печатается при старте);--no-auth— выключить авторизацию (только локальная отладка);--discovery PATH— переопределить путь к discovery-файлу.
Пример:
llao serveПри старте демон печатает адрес, токен и путь discovery-файла; токен нужен
для входа в веб-интерфейс. С другого компьютера открывайте
http://<IP-машины>:18180/ и вводите тот же токен. Если порт не наружу,
разрешите его в файрволе (Windows: netsh advfirewall firewall add rule name="llao" dir=in action=allow protocol=TCP localport=18180). On Linux:
wine llao.exe serve либо нативный ./llao-linux serve.
Одна копия демона на сессию: повторный запуск отвергается (на Windows —
именованный мьютекс Local\llao-singleton) — очередь и tmp-каталог не делятся.
На Linux под wine тот же мьютекс живёт в одном wineserver — обёртка (./llao serve)
гарантирует единый WINEPREFIX, поэтому синглтон работает так же; нативный
./llao-linux serve синглтона не имеет.
Открыть http://127.0.0.1:<порт>/ и ввести токен. Возможности:
- добавление папок/файлов (рекурсивно) в работающую очередь — кнопка «+» в
строке заголовка открывает модальное окно; поле «Выход» задаёт каталог
вывода для обоих режимов: результат пишется в
<целевая папка>/<подкаталог пачки>/<файл>(структура сохраняется), исходники не трогаются; пустое поле — замена на месте; флаг «Восстановление» включает режимrestore. В optimize при заданной целевой папке пишется лучший кандидат, даже если он не меньше исходника (полная конвертация пачки); если победителя нет вовсе (ни один кандидат не прошёл валидацию) — файл пропускается; - статус файлов — цвет фона строки (в очереди / подготовка / работа / готово / остановлен / ошибка); прогресс: для работающих — доля выполненных задач (синий), для готовых — экономия в процентах (зелёный). В режиме восстановления проценты честные: при росте файла убыток показывается серым. Путь результата в колонке «Файл» — относительно целевой папки;
- массовые операции над выделенными строками: остановка, запуск, перемещение в начало/вверх/вниз/в конец, удаление; перетаскивание строк; сортировка по пути;
- пауза всей очереди, перезапуск остановленных, очистка только успешно завершённых;
- статусбар задач в строке заголовка очереди (между «+» и кнопками действий):
доля выполненных задач, включая распаковку файлов в WAV. У строк с
построенным планом — точное число задач; у строк до подготовки — число
вариантов сессии из
formats/*.json(через/api/formats) как предварительная оценка, ничего не засчитывая сделанным (после построения плана цифра заменяется на точную). Клик по статусбару включает/выключает автоскролл за обрабатываемыми файлами (следует и вверх при чистке списка или перемещении активных строк); тёмная полоса прокрутки.
Токен и настройка автоскролла запоминаются браузером. В dev-режиме (запуск
из каталога с исходниками web/ рядом) демон отдаёт файлы прямо с диска —
правки HTML/JS/CSS применяются обновлением страницы без пересборки и без
остановки активных задач; в релизе ассеты вшиты в исполняемый файл.
Все запросы, кроме GET / и /static/*, требуют заголовок
Authorization: Bearer <token>.
| Endpoint | Назначение |
|---|---|
GET /api/state |
снимок: версия, опции сессии, счётчики, пауза, строки очереди |
GET /api/events?since=N |
событийный лог (log/task/state/…) с last_seq для дельты |
GET /api/formats |
список включённых форматов |
POST /rpc |
JSON-RPC: { "cmd": "...", "args": {...} } |
Команды /rpc: ping, stat, add, cancel-file, remove,
bulk-cancel, bulk-remove, clear-done, sort, restart,
pause/cancel-all, resume, reorder, shutdown, formats, debug.
Discovery-файл — %LOCALAPPDATA%/llao/daemon.json на Windows,
$XDG_DATA_HOME/llao/daemon.json на Linux (переопределяется --discovery
или env LLAO_DISCOVERY). Содержит port, token, pid, version —
позволяет клиентам подключиться к работающему демону.
Рядом с discovery-файлом демон держит queue.json (формат version: 2,
порядок строк = порядок очереди). Состояние обновляется при каждом изменении
очереди и в конце shutdown, поэтому:
Не запускайте второй экземпляр демона без указания
--discovery. Он подхватит ту же боевую очередь ($XDG_DATA_HOME/llao/queue.json) и начнёт обрабатывать её параллельно: несколько процессов одновременно пишутqueue.jsonи выжигают все ядра кодеками, а перезапуск «повисшего» тестового экземпляра возможен только через его собственный discovery-файл. Для любых отладок/проверок изолируйте экземпляр:llao serve --port N --discovery /tmp/llao-test/<id>.json—queue.jsonбудет создан рядом с ним и боевая очередь не затрагивается.
- после корректного рестарта демона
ok-строки сохраняются, активные продолжают обработку, остановленные/ошибки — на своих местах с причиной; - строки хранят абсолютный корень (
root) + относительный от него путь (path): очередь не зависит от рабочей директории демона, и перезапуск из любого каталога распознаёт источники (относительные добавления абсолютизируются уже в моментadd); старые строки безrootсохраняют прежнее поведение; - после аварийного завершения (
kill -9, выключение машины) активная обработка не «маскируется»: на следующем старте неоконченные строки помечаютсяостановлено при перезапуске (обработка не завершена), аqueued-строки снова уходят в очередь (справедливо перепроверяются исходники и их sidecar; пропавший файл помечается stopped с причиной); ok-строка восстанавливается с проверкой результата и его sidecar по фактическому пути (out_path).
Запись результата crash-безопасна: кандидат сначала копируется во временный
файл рядом (.<имя>.llao-tmp.<ext>), старый файл удаляется, затем временный
переименовывается на место — без резервной копии и корректным расширением.
Sidecar доставляется той же транзакцией (.<имя>.llao-tmp.tags.zip): если теги
встроены в целевой формат, устаревший <имя>.tags.zip удаляется; если кандидату
внешний sidecar нужен — он атомарно заменяется. При обрыве между шагами queue.json
остаётся с исходной строкой, и следующий запуск честно сообщит о неоконченной
работе, а не покажет ложное «готово».
- Читаются и валидируются конфиги
formats/*.json. tools: для каждого включённого формата находится утилита — кэшbin/<id>/→ PATH → скачивание по URL (SHA-256), распаковка архива или извлечение из установщика через 7-Zip (без установки; скачанный установщик кэшируется и не перекачивается).- Для каждого файла (в отдельном процессе):
- проба (ffprobe) → декод в эталонный WAV; lossy-входы и файлы с видеопотоком пропускаются
(кроме
--allow-lossy); - извлечение канонического набора тегов (текст, картинки, лирика, cuesheet, ReplayGain, главы);
- перебор подходящих форматов и вариантов сжатия;
- для каждого кандидата: кодирование → встроенная проверка → декод → побайтовое сравнение PCM с эталоном → запись тегов (встроенных либо ZIP-sidecar) → валидация тегов;
- победитель = кандидат минимального размера.
- проба (ffprobe) → декод в эталонный WAV; lossy-входы и файлы с видеопотоком пропускаются
(кроме
- Победитель заменяет исходник (с корректным расширением), при необходимости рядом кладётся
sidecar
.tags.zip. - Каждый кандидат пополняет локальную статистику
stats.json— она определяет порядок перебора в следующих прогонах. - Всё логируется и сводится в отчёт: таблица форматов, экономия, причины исключений.
restore возвращает файлы в исходный формат (по умолчанию FLAC) с сохранением
тегов. Интерфейс аналогичен оптимизатору. Для каждого файла — две фазы: декод
исходника → кодирование в целевой формат.
- Каждый встреченный формат тегов (ID3v2, RIFF LIST INFO, Vorbis-коммент, APEv2, ID3v1, MP4 ilst) извлекается как отдельная группа.
- При сжатии одиночная группа конвертируется в нативный тип целевого формата; при нескольких
группах каждая встраивается в свой тип, если цель его поддерживает, иначе — в ZIP-sidecar
(
tags.zipсtags.jsonиpictures/). Конфликтующие группы не сливаются. - При восстановлении (
restore) согласованный набор сжимается в одну нативную группу; старые sidecar v1 тоже читаются. - Стоимость кандидата — размер файла (+ sidecar); данные не теряются никогда.
- Целевая ОС: Windows 10+. Кросс-компиляция MinGW-w64; рабочий тулчейн —
llvm-mingw:
export PATH="$HOME/opt/llvm-mingw-<ver>-…/bin:$PATH" && make. - Dev-контейнер с полным окружением (llvm-mingw + wine32/64 + ffmpeg + p7zip):
make docker-image docker-build(соберётllao.exeиllao-linux),make docker-shell— интерактивная оболочка с проектом в/work. Это удобно для прогона wine-зависимой логики (llao.exe, кодеки) без установки чего-либо на хост. - Нативная Linux-сборка:
make TARGET=linux. Исполняемый файлllaoработает нативно; кодеки (Windows-версии) выполняются под wine. - Запуск под wine:
wine llao.exe …(утилиты кодеков — Windows-версии). На Linux обёрткаllaoподавляет шум wine (WINEDEBUG=-all). - Зависимости для сборки:
nlohmann/jsonиminizлежат вthird_party/. - Собирается один бинарник
llao(llao.exe/llao-linux): движок (optimize*.cpp,tags_*.cpp— декомпозированные модули), событийный слой (serve_*.cpp,serve_internal.h) иmain.cpp(диспетчер подкоманд) линкуются вместе (Makefile). Веб-ассеты вшиваются черезtools/embed_assets.py(перегенерируется при правкеweb/*). - Подробности архитектуры и история декомпозиции монолитов — в
docs/architecture-audit.md. - Схема конфигов форматов — в
formats/README.md.
- Нативные (без wine, собираются g++):
make test-unit test-daemon-core && ./test-unit && ./test-daemon-core. - Интеграционные тесты сервера (нужны собранный
llao-linux,ffmpegв PATH и кодеки вbin/):make TARGET=linuxзатемmake test-daemon(restore → interactions → queue → persist). Каждый тест поднимает свой демон на случайном порту (--no-auth),18180не трогает.test-daemon-persistпокрываетqueue.json, грациозный и аварийный перезапуски очереди и транзакционную доставку sidecar. - CI:
.github/workflows/ci-linux.yml— собирает linux-бинарник, ставит кодеки нативнымllao-linux tools(Windows-версии кодеков выполняются под wine) и гоняет все тесты;bin/кэшируется поformats/*.json. - Релизный прогон (
release.yml, тегv*): сборкаllao.exeпод wine + llvm-mingw, CLI-эталоны кодеков, актуальность версий, перенос тегов и ошибки.
MIT — см. LICENSE. Кодеки в bin/ распространяются под собственными лицензиями
авторов (см. README/LICENSE.txt внутри каталогов форматов).