Снятие видео-скриншотов c камеры Watcher
Эта статься будет полезна вам в следующих случаях:
- При организации видеонаблюдения на объектах, где не требуется постоянно транслировать живое видео со стримеров. Например, если вы установили видеокамеры для наблюдения за стройкой, сельскохозяйственными угодьями или другими медленными процессами, то достаточно будет получать с камеры скриншоты по запросу пользователя/абонента или с заданной периодичностью.
- При разработке собственного веб-интерфейса или мобильного приложения, в котором вы хотите отображать превью с камер, как в Watcher.
API Flussonic Watcher и Flussonic Media Server позволяет реализовать эти сценарии в вашем собственном веб-интерфейсе или приложении.
Это можно сделать с помощью скриншотов в формате MP4. Их использование не требует дополнительных ресурсов, т.к. при их получении не производится конвертация форматов изображения. Такие скриншоты представляют собой экспортированное видео в формате mp4 с одним кадром. После получения скриншота MP4 можно конвертировать его в другие форматы, включая PNG, JPG и т.д., с помощью сторонних утилит, например ffmpeg. Ниже будет приведен пример того, как это сделать. Также вы найдете на этой странице пример встраивания скриншота на веб-страницу.
Предварительная настройка Watcher
Чтобы иметь возможность запрашивать скриншоты, настройте Watcher:
-
Настройте права пользователя, от имени которого будете запрашивать скриншоты. Пользователь должен иметь доступ к папке с требуемыми камерами. Проще всего будет создать для таких камер отдельную Организацию и назначить соответствующего пользователя владельцем этой Организации.
-
Добавьте в созданную Организацию одну или несколько камер, с которых планируете получать скриншоты.
Предварительные запросы
Прежде чем формировать URL для запроса скриншотов, нужно выполнить несколько запросов к API Watcher, чтобы получить необходимые данные:
-
Для отправки любых запросов в Watcher нужен ключ авторизации. В данном случае подойдут ключи x-vsaas-session или x-vsaas-api-key пользователя, настроенного на предыдущем шаге. Подробную информацию об этих ключах и о том, как их получить см. в разделе Способы авторизации API-запроса.
Например, чтобы получить ключ x-vsaas-session, выполните запрос
http://watcher-ip/vsaas/api/v2/auth/login
.curl http://127.0.0.1/vsaas/api/v2/auth/login -H 'Content-Type: application/json' --data-binary '{"login":"API user", "password":"apiuser"}'
В ответе будет параметр session, который и является значением ключа x-vsaas-session.
-
Получив ключ авторизации, выполните запрос
http://WATCHER-IP/vsaas/api/v2/cameras/
.Пример
curl -sS -f -X GET http://127.0.0.1/vsaas/api/v2/cameras -H 'x-vsaas-session: RYABq2AgwlgNXsqSkwSMOcX3InI'
В ответ на этот запрос Watcher вернет параметры камер, доступных пользователю.
Нажмите, чтобы увидеть пример ответа
В данном случае запрос вернул две камеры:
[ { "agent_key": null, "agent_id": null, "thumbnails_url": "", "motion_detector_enabled": false, "static": true, "onvif_profile": null, "groups": [], "precise_thumbnails": false, "enabled": true, "dvr_space": null, "folder_id": 7, "precise_thumbnails_days": 0, "dvr_lock_days": 1, "agent_model": null, "user_attributes": {}, "playback_config": { "token": "2.-s9tHGUHAAEABcXhj_yu3vqQhCc5l9Zv1aS-onP8IcVoG4Pl" }, "thumbnails": false, "folder_coordinates": null, "substream_url": "", "preset": { "vision_alg": null, "vision_params": {}, "vision_areas": null, "is_adjustable": true, "vision_enabled": null, "dvr_depth": 2, "domain_id": 1, "dvr_space": null, "vision_gpu": null, "id": 8, "is_default": true, "dvr_lock_days": 1, "title": "2+1days_adjustable", "is_deleted": false }, "comment": "", "vision_alg": null, "last_change": { "object_type": "Camera", "created_at": 1623922927, "object_id": "samplecamera2-1584a116d9", "user": "admin" }, "streamer_id": 1, "onvif_ptz": false, "preset_id": 8, "dvr_path": "/dvr", "coordinates": "", "permissions": { "dvr": true, "ptz": true, "edit": true, "view": true, "actions": true }, "postal_address": "", "agent_serial": null, "dvr_depth": 2, "organization_id": 6, "video_only": false, "external_id": null, "stream_url": "file://vod/sample-10s.mp4 ", "agent_status": null, "vision_areas": null, "onvif_url": null, "vision_enabled": null, "last_event_time": null, "stream_status": { "alive": false, "lifetime": 5948, "source_error": null, "http_port": 80, "https_port": null, "bitrate": 4294, "server": "localhost" }, "name": "samplecamera2-1584a116d9", "has_actions": false, "vision_gpu": null, "title": "SampleCamera2" }, { "agent_key": null, "agent_id": null, "thumbnails_url": "", "motion_detector_enabled": false, "static": true, "onvif_profile": null, "groups": [], "precise_thumbnails": false, "enabled": true, "dvr_space": null, "folder_id": 7, "precise_thumbnails_days": 0, "dvr_lock_days": 1, "agent_model": null, "user_attributes": {}, "playback_config": { **"token": "2.-s9tHGUHAAEABcXhj_yu3gCkwPvOTwRbY3O60MZ0Qb117UHv"** }, "thumbnails": false, "folder_coordinates": null, "substream_url": "", "preset": { "vision_alg": null, "vision_params": {}, "vision_areas": null, "is_adjustable": false, "vision_enabled": null, "dvr_depth": 1, "domain_id": 1, "dvr_space": null, "vision_gpu": null, "id": 7, "is_default": true, "dvr_lock_days": 1, "title": "1+1days_non-adjustable", "is_deleted": false }, "comment": "", "vision_alg": null, "last_change": { "object_type": "Camera", "created_at": 1623923311, "object_id": "samplecamera4-fd2f695a2e", "user": "admin" }, "streamer_id": 1, "onvif_ptz": false, "preset_id": 7, "dvr_path": "/dvr", "coordinates": "", "permissions": { "dvr": true, "ptz": true, "edit": true, "view": true, "actions": true }, "postal_address": "", "agent_serial": null, "dvr_depth": 1, "organization_id": 6, "video_only": false, "external_id": null, "stream_url": "file://vod/sample-5s.mp4 ", "agent_status": null, "vision_areas": null, "onvif_url": null, "vision_enabled": null, "last_event_time": null, "stream_status": { "alive": false, "lifetime": 6008, "source_error": null, "http_port": 80, "https_port": null, "bitrate": 4081, "server": "localhost" }, "name": "samplecamera4-fd2f695a2e", "has_actions": false, "vision_gpu": null, "title": "SampleCamera4" } ]
Note
Если вам нужна только одна камера и известно ее название в БД, можете запросить параметры только этой камеры:
http://WATCHER-IP/vsaas/api/v2/cameras/(имя_камеры)
. Параметры ответа будут такими же.Вам понадобятся параметры server, name и token для требуемой камеры.
Теперь можно формировать URL для получения скриншотов.
Формирование URL
Запрашивая скриншоты с камеры, вы обращаетесь напрямую к стримеру, т.е. используете API Flussonic Media Server.
Для каждой камеры нужно сформировать отдельную ссылку для запроса скриншотов, используя полученные выше параметры:
Скриншот живого потока:
http://server/name/preview.mp4?token=token
Пример
http://127.0.0.1/samplecamera2-1584a116d9/preview.mp4?token=2.-s9tHGUHAAEABcXhj_yu3vqQhCc5l9Zv1aS-onP8IcVoG4Pl
Также можно запросить скриншоты из архива, если для камеры настроен DVR. Порядок и особенности формирования ссылки с указанием времени см. на странице Видео-скриншоты. Обратите внимание, что к сформированному запросу нужно будет добавить параметр token, как в примерах выше.
Пример запроса скриншота MP4 за дату 29.07.2021, 14:26:24 UTC+0
http://127.0.0.1/samplecamera2-1584a116d9/2021/07/29/14/26/24-preview.mp4?token=2.-s9tHGUHAAEABcXhj_yu3vqQhCc5l9Zv1aS-onP8IcVoG4Pl
Если именно в этот момент времени архив не записывался, то Flussonic Media Server вернет ближайший доступный скриншот (в пределах 10 минут).
Конвертирование скриншота MP4 в другие форматы с помощью ffmpeg
В первую очередь убедитесь в том, что у вас установлена утилита ffmpeg. Загрузите файл скриншота в формате MP4 на диск.
Пример команды для конвертации скриншота в формате MP4 в формат PNG:
ffmpeg -i preview.mp4 preview.png
В зависимости от того, в каких директориях находятся файлы утилиты и скриншота, может потребоваться указать полный путь к файлам.
Пример скрипта для показа MP4 скриншотов в браузере
Ниже приведен простой пример скрипта на JavaScript для отображения скриншотов MP4 с одной камеры в любом браузере.
В параметре src
тега <video>
укажите ссылку на скриншот живого потока, сформированную как показано выше.
Скриншоты будут обновляться с заданной периодичностью 5 секунд (5000 миллисекунд). Если вам требуется другая периодичность, задайте параметру VIDEO_UPDATE_DELAY
требуемое значение в миллисекундах.
Также обратите внимание, что для корректного отображения скриншота в ссылке должно быть указано время #t=1
. В примере ниже этот параметр добавляется к ссылке в функции updateVideo ()
. Если что-то пойдет не так, например ваш браузер неправильно обработает этот скрипт, попробуйте добавить параметр времени к ссылке в параметре src
и убрать дополнение URL из функции.
<video id="previewSource" crossorigin="anonymous"
src="http://server:80/name/preview.mp4?token=token"
autoplay playsinline/></video>
<script>
(function() {
const VIDEO_UPDATE_DELAY = 3000;
var previewSource = document.getElementById("previewSource");
const videoSrc = previewSource.getAttribute('src');
function updateVideo () {
const nextVideoUrl = new URL(videoSrc);
nextVideoUrl.hash = '#t=1';
nextVideoUrl.searchParams.set('v', Date.now());
previewSource.setAttribute('src', nextVideoUrl.href);
}
updateVideo();
previewSource.addEventListener("loadeddata", function() {
window.setTimeout(updateVideo, VIDEO_UPDATE_DELAY);
});
}());
</script>
Встраивание MP4 скриншотов в мобильное приложение
Watcher предоставляет SDK для разработки мобильных приложений для iOS и Android. Помимо прочего, в SDK есть инструменты для работы с MP4 скриншотами:
- Компонент FlussonicThumbnailView для отображения скриншотов в приложении на Android.
- Функция
PreviewMp4View
для отображения скриншота в приложении на iOS.
Примеры использования этих инструментов можно найти в демо-приложении под iOS и Android.