Я использую внешнюю камеру с ffmpeg для получения подводной прямой трансляции. Теперь я хочу добавить некоторые динамические значения (текстовое наложение) поверх видеопотока и перенаправить его на какого-то внешнего провайдера, например, на YouTube в прямом эфире... Мои значения получены от разных датчиков (температура, кислород, соленость и т. д.), и эти значения должны быть встроены в видеопоток.
Каков правильный или «лучший» или «правильный» способ сделать это?
Этот вопрос немного похож на вопрос « Я пытаюсь добавить гитарные табы в музыкальное видео». Знаете ли вы какое-нибудь программное обеспечение для этого?
Во-первых, в каком формате ваши данные, какой протокол используется с ваших датчиков? Я думаю, здесь какое-то программное обеспечение с закрытым исходным кодом и проприетарный протокол для датчиков? Очевидно, вам нужно программное обеспечение, которое может читать этот формат данных/протокол. Если вы создаете собственную систему с микроконтроллерами, постарайтесь найти удобный и открытый протокол для данных. Очень сложно найти открытые протоколы с необходимой функциональностью.
На данный момент, я думаю, вы нашли любой подходящий протокол. Например, JSON с произвольными полями. Теперь попробуйте найти/написать софт, который будет его использовать.
Один из возможных способов: написать веб-приложение, которое будет отображать видеопоток в вашем браузере, подгружать данные с датчиков и отображать забавный оверлей. Затем просто захватите видео с экрана и транслируйте на YouTube или любой другой сервис. Это "грязный" способ, но он сработает.
Другой способ: написать собственный фильтр в ffmpeg. Вы можете использовать ass-renderer для справки, как добавить текст на изображение. Просто добавьте данные о показаниях ваших датчиков, и ваша задача будет выполнена.
Иногда нам нужно как-то отфильтровать видео, может быть, добавить какой-нибудь текст или графику поверх. Написать полноценное приложение, которое распаковывает видеопоток, насыщает изображение новыми элементами или изменяет само изображение, а затем заново сжимает поток, несколько сложно. Сегодня мы научимся быстро и грязно делать такие приложения, не зная, как кодировать видео вообще.
Для начала вспомним, что изображения состоят из строк и столбцов точек, которые называются пикселями. Каждая точка состоит из 3 или 4 компонентов, обычно красного, зеленого и синего сигналов, иногда присутствует альфа-канал. Следовательно, чтобы изменить 1 точку изображения, нам нужно изменить 3-4 компонента (обычно это 3-4 байта). Итак, чтобы изменить все изображение, нам нужно изменить все строки и столбцы, в каждом из 3-4 элементов и как-то модифицируя их, сохранить обратно. Например, если у нас есть картинка размером 256х192 пикселя в формате RGB24, то в ней будет 49152 пикселя и 147456 цветовых составляющих (байт).
Поэтому нам нужно просто прочитать куски по 147456 байт, как-то модифицировать их и записать обратно! Это все! Никаких сложных библиотек или алгоритмов не требуется! Где взять эти байты? А получить их мы можем с замечательной утилитой ffmpeg и ее не менее прекрасным режимом rawvideo, выхлоп которого мы отдадим на stdout и получим в stdin ваше приложение!
Напишем простейшее приложение, которое немного изменит изображение:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main () {
// allocate variables and buffer
uint8_t *pixels = malloc (147456);
uint8_t *pix;
int q;
while (1) {
// read frame
if (fread (pixels, 1,147456, stdin) <= 0) {break;}
// process image
pix = pixels;
for (q = 0; q <49152; q ++) {
*pix++ = *pix * 2; // multiple red to 2
*pix++ = *pix + 120; // shift green channel
*pix++ = *pix + q / 10; // lines in blue channel
}
// write frame back
fwrite (pixels, 1,147456, stdout);
}
return EXIT_SUCCESS;
}
Да, это все! Конечно, здесь все константы жестко запрограммированы, никогда так не делайте в реальных проектах!
Теперь запустите это и загрузите видео сюда:
ffmpeg -i video.mp4 -s 256x192 -f rawvideo -pix_fmt rgb24 - | ./a.out | ffmpeg -s 256x192 -f rawvideo -pix_fmt rgb24 -i - -y out.mp4
И получаем следующий результат:
Проанализируем, какие параметры в этой строке участвовали:
ffmpeg -i video.mp4 -s 256x192 -f rawvideo -pix_fmt rgb24 -
Здесь читаем из файла video.mp4
, меняем размер картинки на 256x192
(если у вас видео уже размером 256х192, то можно этого не делать), далее указываем, что его нужно преобразовать в rgb24
цветовое пространство (если его еще нет в нем, то какой ибо может потратить довольно много ресурсов), а результат нам нужен в виде несжатого видео rawvideo
, результат мы записываем в формате -
, т.е. в формате stdout
.
| ./a.out |
А это наше приложение. Вертикальные «трубки» означают, что он будет брать данные из предыдущего приложения и передавать их следующему.
ffmpeg -s 256x192 -f rawvideo -pix_fmt rgb24 -i - -y out.mp4
Здесь мы указываем, что на вход этого ffmpeg будет несжатое видео по rawvideo
формату, размеру 256x192
и rgb24
цветовому пространству. Также может понадобиться указать fps, так как при таком преобразовании он теряется. Вывод будем записывать в out.mp4
, и даже если такой файл уже существует, за -y
это отвечает параметр
Вот очень простой пример смены изображения, но вы можете накладывать текст, другие картинки и все что угодно. Конечно, лучше написать полноценное приложение или хотя бы пропатчить уже существующий фильтр до нужного состояния, это будет более правильное решение. Но если вам нужно работающее решение, при этом вы не хотите писать много кода, то это решение для вас.
ffmpeg -i _SOURCE_ -f rawvideo -pix_fmt rgb32 - | ./your_app | ffmpeg -f rawvideo -pix_fmt rgb32 -i - rtmp://broadcast.to.server/
. Это будет передавать кадры в ваше приложение через стандартный ввод, затем вы можете рисовать на нем и передавать растровые изображения в стандартный вывод, где новый экземпляр ffmpeg будет кодировать их и сохранять в файл/трансляцию.
Гьян
Салем Ф.
.m3u8
файлы, скажем, два изображения, которые заставятffmpeg
постоянно загружать эти изображения, поэтому вы можете изменить/заменить/обновить эти файлы изображений иffpmeg
загрузить их быстро