- json-api-for-spa: адреса приложения уехали в своё пространство /app/, приём стал POST /app/audiorecords, опрос /api/status/:id убран, заведены список, карточка, текст, /app/me и /app/config; имя файла отправителя легло своей колонкой рядом с заголовком - три действия над записью — правка заголовка, возврат в работу и журнал событий — собраны задачей audiorecord-actions - голова очереди: контракт, каркас, экран загрузки, список, действия - в прежних задачах поправлены адреса, рубежи конвейера и остатки Telegram
53 lines
4.6 KiB
Markdown
53 lines
4.6 KiB
Markdown
# ✨ Проигрывать загруженную запись на экране записи
|
||
|
||
- **Тип:** feature
|
||
- **Категория:** Очередь — Проигрывание живёт на экране записи, которого до списка нет.
|
||
- **Зачем:** Послушать загруженное приложение не даёт, а самой копии для этого у задачи нет: указатель на файл перезаписывается на каждом шаге конвейера и у готовой задачи ведёт на объект в Object Storage.
|
||
|
||
Запись слушается на её экране, а не скачивается файлом.
|
||
|
||
Заметка владельца от 2026-08-12. Копии на диске остаются все три — исходник,
|
||
ogg после конвертации и запись об объекте, — но `job.FileID` на каждом шаге
|
||
указывает на последнюю: у задачи в `done` он ведёт на объект Object Storage, а
|
||
местные копии не связаны с задачей ничем. Значит, задача не только про экран:
|
||
проигрываемую копию сперва нужно к записи привязать.
|
||
|
||
Берётся после `records-list-screen` — экран одной записи делает она.
|
||
|
||
## Затрагивает
|
||
|
||
- связь задачи с копией: сегодня `transcribe_jobs.file` — одно поле на одну
|
||
копию, и шаг схемы придётся добавлять;
|
||
- контракт HTTP API из `json-api-for-spa` — признак наличия аудио в ответе о
|
||
записи;
|
||
- экран одной записи из `records-list-screen`;
|
||
- `GET /app/audiorecords/{id}/audio` — свой адрес отдачи копии, с поддержкой
|
||
`Range`: ссылка хранилища в ответ не выходит, это норма `storage`. Отдачу
|
||
пишем сами, и оба свойства чужого адреса переходят к нам обязанностью — ответ
|
||
на `Range` и тип содержимого, при котором копия проигрывается, а не
|
||
скачивается вложением;
|
||
- периметр из [ADR-2026-08-12](../../docs/adr/ADR-2026-08-12-file-link-open-but-not-logged.md):
|
||
ссылка на файл открыта знанием записи, и экран делает её видимой странице;
|
||
- `docs/architecture.md` — какая копия считается проигрываемой.
|
||
|
||
## Критерии приёмки
|
||
|
||
- Готовая запись проигрывается с её экрана, без скачивания файла. Оракул — тест
|
||
экрана на подставном API: у проигрывателя есть источник, и он начинает играть.
|
||
- Задача в `done` указывает на копию, пригодную для браузера. Оракул — тест
|
||
конвейера: после полного прохода у задачи есть адрес местной копии, а не
|
||
только ключ объекта.
|
||
- Запись, ещё не дошедшую до текста, экран тоже даёт послушать. Оракул — тест на
|
||
задаче в состоянии `transcribe`: проигрыватель на экране есть.
|
||
- Копия отдаётся так, что её берёт проигрыватель браузера, и перемотка работает
|
||
на записи длиннее часа. Оракул — два запроса к адресу копии: обычный отвечает
|
||
типом и заголовком `Content-Disposition`, при которых элемент `audio` играет,
|
||
а запрос с `Range` — кодом `206` и запрошенным куском.
|
||
|
||
## Рамки
|
||
|
||
Скачивания файла, обрезки и синхронизации текста со звуком не делаем. Записи
|
||
звука в приложении не делаем — это граница из паспорта. Формат хранения и раскладку
|
||
каталога данных не трогаем: они объявлены необратимыми, а шаг схемы, уехавший на
|
||
сервер, не переписывается — изменение только новым файлом шага.
|