Перейти к основному содержимому

Mini-player и live-виджет

На сайте mini-player и live-виджет подключаются через Web SDK. В нативном приложении product video открывается через Mobile SDK. Public API используется для согласованного кастомного интерфейса и серверной диагностики.

ЗадачаПодход
Показать mini-player на карточке товараWeb SDK и настройка шаблона товара со стороны ShopStory.
Показать product video в нативном приложенииMobile SDK и native PDP с тем же feedProductId, что в фиде.
Показать виджет текущего эфираWeb SDK; виджет появляется только при активном live.
Получить состояние одного товараGET /v2/mini-player/stream-state.
Проверить наличие текущего liveGET /v2/mini-player/online.
Получить краткое состояние известного эфираGET /v3/translation/quick-state.
Показать отдельный результат stock-check до cart-командыAPI продавца в рамках custom commerce; mini-player API этого не делает.

Веб-интеграция

После регистрации домена и настройки идентификатора товара со стороны ShopStory добавьте скрипт в конец <body> на страницах, где разрешён виджет:

<script
id="shopstory-pip"
type="application/javascript"
src="https://app.shopstory.live/sdk/shopstory-pip-sdk/shopstory-pip-sdk-v1.x.min.js"
crossorigin="anonymous"
charset="utf-8"
async
></script>

v1.x входит в production URL буквально. Используйте имя файла без замены x.

Этот auto-init bundle работает отдельно от основного ShopStorySDK.show(): он не получает объект actions из каталога и не должен загружаться вместе с основным bundle без схемы из integration handoff. Базовое действие в player, открытом из mini-player, ведёт на URL товара. Direct cart для этого пути оформляется как кастомная commerce-интеграция.

В зависимости от конфигурации проекта скрипт подключает:

  • mini-player на карточке товара, если с товаром связан live или VOD;
  • live-виджет во время текущего эфира.

В MPA скрипт можно подключить в общем шаблоне сайта, исключив корзину и checkout. Для SPA ShopStory отдельно проверяет router lifecycle и смену DOM/SKU. В обоих случаях стороны согласуют селектор или источник идентификатора товара, разрешённые домены и включённые компоненты.

Отдельный DOM-контейнер для PiP создавать не нужно: скрипт добавляет свой контейнер в document.body. Товарный ID должен оставаться доступным в согласованном месте на PDP. Если существующая разметка не даёт получить ID, её потребуется дополнить. Подробности: Product mini-player в Web SDK.

Порядок загрузки на PDP

  1. Браузер загружает скрипт с async параллельно разбору HTML.
  2. SDK определяет конфигурацию сайта и товар на PDP. Если включён показ после прокрутки, проверка контента начинается при достижении заданного порога; без этого условия — при инициализации виджета.
  3. SDK асинхронно запрашивает stream-state для товара. При включённом live-уведомлении параллельно проверяется online.
  4. После ответа SDK запрашивает готовое превью либо поток для продолжения просмотра. Открытие PDP не запускает обработку видео на сервере.

Порог прокрутки может применяться только к первому показу. При такой настройке возврат из полного плеера с подходящим состоянием Continuous Video проходит без ожидания прокрутки.

Отрисовку PDP, загрузку цены и работу корзины не нужно связывать с готовностью PiP. При no_active_stream товарный виджет не появляется, файл превью и HLS для него не запрашиваются. Скрипт и запрос состояния остаются частью загрузки страницы. Если отдельно включено live-уведомление, оно может появиться и без связанного с товаром видео.

Выполнение JavaScript, сеть и декодирование видео используют ресурсы браузера даже при асинхронной загрузке. При приёмке сравните LCP/INP и Network на одной PDP с включённым и отключённым PiP. Подробнее: MDN: script async.

Минимальная проверка:

  1. Идентификатор товара на странице совпадает со строковым идентификатором в согласованном фиде.
  2. stream-state возвращает body.status: "active" для тестового товара.
  3. ShopStory включил mini-player для текущего домена и шаблона карточки товара.
  4. Content Security Policy сайта разрешает согласованные источники ShopStory.
  5. На PDP без готового контента товарный PiP скрыт и не запрашивает медиа.
  6. Если включён Continuous Video, пройдите путь «полный плеер → товар → полный плеер»: проверьте позицию VOD, возврат в той же вкладке и управление звуком.

Ответ active описывает состояние серверной части. Отрисовка на странице отдельно зависит от настройки DOM-шаблона.

Режимы PiP на PDP

PiP — плавающий виджет внутри страницы товара. Виджет автоматически оказывается в одном из состояний ниже — режим не выбирает ни интегратор, ни посетитель. ShopStory включает нужные режимы и профиль медиа в конфигурации проекта, а скрипт выбирает состояние по пути входа посетителя, статусу эфира товара и поддержке браузера. В ранее настроенных интеграциях могут сохраняться GIF-превью.

РежимКогда возникаетЧто видит посетитель
Превью записиПрямой вход на PDP; с товаром связан завершённый эфир с готовым превьюКороткий WebM-клип с субтитрами, повторяется по кругу; полный VOD для этого не загружается. Клик — полный плеер около эпизода
Live в PiPПрямой вход на PDP; эфир товара идёт сейчас и режим включён в конфигурации проектаТекущий эфир без звука с текущего момента. Клик — полный плеер с live
Continuous VideoПосетитель пришёл на PDP из полного плеера, и сохранённое состояние просмотра соответствует товару и эфируТа же запись или тот же live с сохранённой позиции; медиапоток загружается по мере необходимости. Попытка продолжить со звуком
ПостерПревью или live недоступны, формат не поддержан либо произошла ошибка медиаСтатичный JPEG из того же эпизода; при недоступном постере — статический фон

Деградация до постера происходит автоматически: виджет не остаётся в состоянии бесконечной загрузки.

Превью записи с субтитрами

ShopStory заранее создаёт клипы из связанных с товаром записей. Приоритет получает эпизод об этом товаре; если подходящего момента нет, возможен общий фрагмент связанного эфира. API выбирает для PDP одно готовое превью.

Параметры используемого профиля коротких превью:

ПараметрЗначение
Контейнер и кодекWebM / VP9.
Длительность10 секунд, повтор по кругу.
Кадр240 × 426 пикселей, 15 кадров/с.
АудиоЗвуковой дорожки нет.
СубтитрыУже наложены на кадры; клиенту не нужны загрузка субтитров, синхронизация или отдельный слой текста.
ПостерОтдельный JPEG из того же эпизода.

Средний размер превью — около 128 кБ; 90% файлов не превышают 182 кБ. Замер на 6 сентября 2026 года: 241 файл, выбранный API для 241 товара одного рабочего каталога; 1 кБ = 1000 байт. Размеры относятся к одному клипу, без скриптов, постера и служебных запросов. Это ориентир для оценки трафика, не гарантированный предел.

Превью воспроизводится внутри страницы. Если браузер сообщает, что VP9 не поддерживается, SDK показывает постер без запроса WebM. При ошибке загрузки или воспроизведения SDK также переходит на постер; при недоступном постере остаётся статический фон.

Клик открывает полный плеер около выбранного эпизода. Субтитры короткого превью не означают, что субтитры включены для всей записи.

Live в PiP

Когда эфир, связанный с товаром, идёт прямо сейчас, ShopStory может включить для проекта показ этого эфира в PiP — без предварительного открытия полного плеера.

  1. Посетитель заходит на PDP во время эфира. PiP показывает текущий live с актуального момента, без звука.
  2. Посетитель включает звук кнопкой в PiP. Состояние звука действует только в рамках текущего показа и не сохраняется между визитами.
  3. Клик открывает полный плеер с текущим эфиром.
  4. После завершения эфира и обработки записи PiP на этом PDP переключается на превью записи.

Пока эфир идёт, PiP показывает live, а не превью записи — даже если превью прошлых эфиров уже готово. Трафик зависит от качества потока и длительности просмотра; размер короткого WebM-превью к этому режиму не относится. При ошибке потока SDK показывает постер или статический фон.

Continuous Video: полный плеер → PDP → полный плеер

Этот режим сохраняет просмотр при переходе к товару. Для него полный Web SDK и PDP размещают на одном origin сайта продавца, а переход выполняют в той же вкладке.

  1. Пользователь нажимает фото или название товара в полном плеере. SDK сохраняет эфир, товар и позицию просмотра, затем открывает URL товара из фида. Кнопка «Купить» выполняет отдельное действие и сама по себе этот переход не запускает.
  2. PiP возобновляет просмотр, если сохранённое состояние просмотра соответствует товару и эфиру из ответа API. Скопированной ссылки без состояния просмотра в этой вкладке недостаточно.
  3. VOD продолжается с сохранённой позиции, live — с текущего эфира. HLS загружается по необходимости в отдельном iframe. При переходе между HTML-страницами возможна пауза на загрузку и буферизацию.
  4. Возврат из PiP открывает полный плеер в той же вкладке и передаёт актуальную позицию VOD.

Для продолжения просмотра нужен доступ к sessionStorage. Серверные редиректы и маршрутизатор должны сохранять параметры перехода, добавленные SDK, до инициализации PiP. Состоянием просмотра управляет SDK.

PiP пытается продолжить воспроизведение со звуком. Если браузер запрещает такой autoplay, видео запускается без звука; пользователь включает его кнопкой в PiP. Эти ограничения задаёт браузер: MDN: autoplay. При ошибке медиапотока SDK использует доступное превью или постер.

В Continuous Video трафик зависит от качества потока и длительности просмотра. Размер короткого WebM-превью к этому режиму не относится.

Состояние по товару

GET https://app.shopstory.live/v2/mini-player/stream-state?application=<application-id>&feedProductId=<feed-product-id>
Accept: application/json
ПараметрОбязательноОписание
applicationДаВыданный ShopStory идентификатор приложения. Он не является секретом или способом авторизации.
feedProductIdДа для новых интеграцийКанонический строковый идентификатор товара из согласованного фида.
productCodeТолько по legacy-контрактуСтроковый артикул продавца для ранее согласованных интеграций с поиском по vendorCode.
feedProductGroupIdТолько по legacy-контрактуДополнительная группа товара. Используется только вместе с productCode, если такой маппинг уже согласован.

В новой интеграции используйте один feedProductId во всех поверхностях. Не чередуйте его с productCode и не передавайте оба параметра одновременно. Идентификаторы должны оставаться строками, включая ведущие нули.

Найден live или VOD

{
"serverTime": "2025-01-15T10:00:00.000Z",
"status": 200,
"body": {
"status": "active",
"stream": {
"streamId": "stream-123",
"streamStatus": "completed",
"productId": "product-456",
"feedProductId": "0001001",
"playbackLink": "https://media.example.net/stream.m3u8",
"previewUrl": "https://media.example.net/preview.webm",
"posterUrl": "https://media.example.net/poster.jpg",
"startTime": 120,
"mediaOrientation": "portrait",
"playerUrl": "https://app.shopstory.live/sdk/"
}
}
}
Поле body.streamОбязательноОписание
streamIdДаСтроковый идентификатор эфира.
streamStatusДаonline или completed.
productIdДаВнутренний идентификатор товара ShopStory.
feedProductIdНетИдентификатор из фида. Может отсутствовать у ранее загруженных товаров или при поиске по productCode.
playerUrlДаГотовый HTTPS URL WebView-плеера. Считайте его непрозрачным и передавайте без изменения.
mediaOrientationДаportrait, landscape, square или unknown.
playbackLinkДаСовместимое поле медиапотока. Не определяйте по нему видеопровайдера и не собирайте из него playerUrl.
previewUrl, posterUrlНетГотовые HTTPS URL превью и статического постера. Превью может быть видео или анимированным изображением в зависимости от профиля. Используйте URL без изменения; не подменяйте расширение файла.
startTimeНетНеотрицательное смещение релевантного эпизода VOD в секундах.

В ручной web-интеграции открывайте playerUrl без изменения. В нативном приложении Mobile SDK выполняет lookup и возвращает типизированный entrypoint, а приложение отдельно передаёт его в SDK coordinator для открытия плеера. Не конструируйте URL плеера из streamId, playbackLink или других полей. Ответ может содержать дополнительные диагностические поля. Игнорируйте неизвестные поля и не используйте их для бизнес-логики.

Связанного эфира нет

Когда связанный live или VOD не найден, API возвращает HTTP 200 с no_active_stream:

{
"serverTime": "2025-01-15T10:00:00.000Z",
"status": 200,
"body": {
"status": "no_active_stream",
"stream": null
}
}

Это штатное отсутствие готового контента: с товаром может не быть связанного эфира либо его запись ещё не готова к показу. В Web SDK товарный PiP в этом состоянии не загружает превью или HLS. В ручной интеграции также скрывайте точку входа и не запрашивайте медиа.

Сейчас API возвращает no_active_stream. Неизвестное значение status обрабатывайте как отсутствие контента: скрывайте точку входа и не открывайте stream.

Ошибки запроса

Этот эндпоинт выставляет HTTP-код ошибки и повторяет его в JSON-конверте:

{
"serverTime": "2025-01-15T10:00:00.000Z",
"status": 400,
"body": {
"error": "invalid",
"message": "Bad request: either 'productCode' or 'feedProductId' must be provided"
}
}
  • HTTP 400 — отсутствует application либо оба идентификатора товара.
  • HTTP 500 — серверная часть не смогла сформировать воспроизводимый источник.

Скрывайте контейнер при no_active_stream, транспортной ошибке, невалидном ответе или если playerUrl отсутствует либо не является HTTPS URL.

Текущий live

GET https://app.shopstory.live/v2/mini-player/online?application=<application-id>
Accept: application/json

При наличии эфира body.online содержит streamId, streamStatus: "online" и playbackLink. Игнорируйте неизвестные дополнительные поля.

Если live сейчас нет, эндпоинт возвращает успешный ответ с пустым объектом body:

{
"serverTime": "2025-01-15T10:00:00.000Z",
"status": 200,
"body": {}
}

Отсутствующий application возвращает HTTP 400 и такой же status в конверте.

Краткое состояние эфира

GET https://app.shopstory.live/v3/translation/quick-state?translationId=<stream-id>
Accept: application/json
{
"status": 200,
"serverTime": "2025-01-15T10:00:00.000Z",
"body": {
"translationState": "completed",
"translationId": "stream-123",
"expires": "2025-01-15T10:01:00.000Z"
}
}

translationState принимает draft, confirmed, online, completed или пустую строку, если состояние неизвестно. Отсутствующий translationId возвращается как HTTP 200 с status: 400 внутри конверта.

Если вызываете эндпоинт периодически, обрабатывайте HTTP 429 и 5xx с увеличивающейся задержкой и случайным разбросом. Не используйте его для проверки товарного остатка.

Мобильные приложения

В нативном приложении lookup и открытие выполняются через Mobile SDK. Lookup возвращает active, unavailable или техническую ошибку. Для active приложение передаёт entrypoint в SDK coordinator, после чего host app открывает плеер.

WebView bridge из web-примеров в mobile contract не входит. Открывайте плеер через SDK coordinator. Маршрутизация товара и добавление в корзину остаются в приложении продавца. Оно получает текущий остаток, цену, авторизацию и результат операции из своих commerce-систем. Точная версия пакета и host contract передаются в integration handoff.

Диагностика

НаблюдениеЗначениеПроверка
body.status: "no_active_stream"Для идентификатора нет готового live/VOD.Сверьте feedProductId или согласованный productCode с фидом и привязкой эфира.
body.status: "active", виджета на странице нетСерверная часть нашла эфир, но web-компонент не отрисован.Проверьте домен, CSP и настройку шаблона карточки товара.
Вместо движущегося превью виден постерБраузер не поддерживает кодек либо медиа не загрузилось.Проверьте поддержку VP9, запрос к previewUrl и ошибки media/CSP в браузере.
Во время эфира в PiP нет liveРежим Live в PiP не включён в конфигурации проекта либо эфир не связан с товаром.Проверьте streamStatus: "online" в ответе stream-state и согласуйте включение режима с ShopStory.
После перехода из плеера началось короткое превьюУсловия Continuous Video не выполнены.Проверьте включение режима, общий origin, ту же вкладку, доступность sessionStorage и совпадение товара/эфира.
Continuous Video воспроизводится без звукаБраузер мог отклонить autoplay со звуком.Включите звук кнопкой PiP; проверьте сценарий на целевых устройствах.
body.online отсутствуетТекущего live нет.Проверяйте VOD через stream-state для известного товара.
translationState: "completed"Эфир завершён.Используйте playerUrl из stream-state для связанного товара.

Связанные разделы