Все версии

Медиаконтент: загрузка, обработка и использование

Дата: 01.11.2026. Статус: исторический эталон дизайн-бука (демо-передача и локальные данные). Внедрено в P09-P11: Bc* и Ds* медиа, см. действующие компоненты. Открыть процесс · Рендеры состояний · PDF · Проверки.

Сверка с действующей системой

Цель - согласовать эти механики, а не заменить их вторым независимым конвертером. Общий источник токенов и адаптеры Element Plus/Bc* сохраняются.

Компонентная схема

| Компонент | Владеет | Контракт | | --- | --- | --- | | MediaDropzone | Выбор, несколько файлов, drag/keyboard | File[], ограничения, объяснение принимаемых форматов | | FileValidation | Размер, MIME/расширение, сигнатура, возможность декодирования | Различимые причины отказа; это предварительная проверка, не доверенная серверная валидация | | MediaQueue | Независимые задачи и действия | Статус по каждому файлу, частичный успех, выбор файла, повторы, отмена | | UploadProgress | Передача | bytesSent/bytesTotal и доступный progressbar; 100% не означает готовность медиа | | ProcessingJob | Очередь и преобразование | jobId, stage, revision, progress или unknown, отмена/повтор и причина ошибки | | RenditionProfile | Формат и требования | MIME/контейнер/кодек, размеры, fit/crop, прозрачность, звук, fps/битрейт при наличии в API | | ImagePreview | Изображение целиком, прозрачность, крупный просмотр | Без незаметной обрезки, с fallback при ошибке | | VideoPlayer | Воспроизведение, пауза, seek, громкость/полный экран нативного плеера | metadata/waiting/playing/paused/ended/error; без autoplay со звуком | | PosterPicker | Кадр из видео | Текущий кадр в PNG, источник/время; объектный URL освобождается при удалении | | MetadataEditor | Название, описание, HTTPS-ссылка, метки | Валидация, dirty/saving/saved/error, сохранение ввода, защита от позднего ответа | | AssetPicker | Добавление готового результата | Только ready + сохраненные метаданные; это не публикация и не модерация |

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

Этапы и действия

выбор -> проверка -> готов к отправке -> передача -> очередь -> обработка -> готово
            |                              |                      |
         отклонен                        ошибка                 ошибка
                                           -> повтор             -> повтор/профиль
передача / очередь / обработка -> отменено -> повтор
произвольное видео + профиль конвертации -> нужен сервер -> оригинал / другой путь

У файла собственная ошибка и результат. Ошибка одного не отменяет готовые файлы. В очереди нет выдуманного процента/ETA. В продукте процент конвертации отображается только если его сообщил сервер; иначе текущий этап и неопределенный индикатор. Отмена увеличивает ревизию локального задания; поздний результат не применяется. Повторный запуск блокируется, пока работает текущая очередь. Фокус на действиях задачи сохраняется при обновлении прогресса.

Что действительно работает в образце

Что показано как демонстрация

Передача, серверная очередь, конвертация видео и сетевые ошибки не подключены к рабочему API. Переключатель «Сценарий следующей обработки» явно позволяет увидеть ошибку передачи/обработки, отсутствие связи, долгое ожидание и успех. Повтор действует на проблемную задачу; другие файлы не требуют повторной загрузки.

Произвольное загруженное видео не заменяется демо-роликом и не получает ложный статус конвертированного MP4. Для такого файла профиль MP4 приводит к «Нужен сервер»; можно выбрать исходник без конвертации. Реальный MOV/MKV, аудио, субтитры, пакетная транскодировка, восстановление после reload и серверная модерация остаются задачами интеграции. Изменения образца не пишут в рабочую библиотеку.

Эталон сервера для внедрения

  1. Preflight: сервер проверяет контейнер/кодеки/длительность/размеры и права.
  2. UploadSession: sessionId, ограничения, bytesTotal, повторяемые части, expiration; возобновление после обрыва по подтвержденным частям.
  3. Finalize: idempotency key, assetId, неизменяемый исходник. Процент передачи и ожидание finalization - разные состояния.
  4. TranscodeJob: sourceAssetId, profileId/version, jobId, queued/processing/ ready/failed/cancelled, stage, errorCode/retryable, resultAssetId.
  5. Наблюдение SSE/polling: монотонная revision, backoff, восстановление по jobId, отсев устаревших ответов; отмена подтверждается сервером.
  6. Результат: проверенный MIME/контейнер/кодек, размеры, длительность, размер, fps, битрейт и звук при наличии; URL, срок действия и fallback.
  7. Метаданные: отдельная revision/ETag, конфликт 409/412, сохранение пользовательского ввода; смена файла/профиля не перезаписывает данные другого выбранного ассета.
  8. Готовность обработки, доступность для объявления и статус модерации разделены.

Приемка и очередь внедрения

58/58 проверок пройдены. check.mjs: unit-проверки контрактов и Chromium-сценарии настоящего декодирования, конвертации, плеера, постера, ошибок, повторов, отмены и метаданных. Снимки светлой/темной тем, 320/390/768/1280/1440, PNG и PDF рядом. Количество проверок и их результат - в checks.json. Общий каталог и форма кампании проверяются отдельно.

| Шаг | Область | Статус | | --- | --- | --- | | M0 | Эталон UX, состояния, локальные сценарии и рендеры | Готово | | M1 | Единый MediaDropzone/валидация/очередь в адаптерах | Не начато | | M2 | UploadSession, прогресс, возобновление, ошибки API | Не начато | | M3 | TranscodeJob и профили, polling/SSE, отмена и восстановление | Не начато | | M4 | Viewer/Player/Poster/MetadataEditor поверх реальных ассетов | Не начато | | M5 | Сквозная приемка и синхронизация DSP/SSP | Не начато |

M1-M4 используют контракты DS1/DS3, не создают дублирующие поля/окна/списки. Для M5 нужны настоящие API и проверка доступности кодеков на целевых устройствах.

Повтор из dsp-web при http.server на 4325: node design-book/components/media/check.mjs.

Фикстуры созданы локально, без внешних материалов: ffmpeg -f lavfi -i testsrc2=size=1280x720:rate=24:duration=4 -c:v libvpx-vp9 -b:v 650k -an source.webm, затем ffmpeg -i source.webm -vf scale=640:360 -c:v libx264 -crf 26 -pix_fmt yuv420p -movflags +faststart -an result-360.mp4.