Blog/content/posts/2023/ffpmeg/text-on-stream.md

5.8 KiB
Raw Blame History

title date draft tags
🎥 Наложние текста на видео поток через ffmpeg 2023-05-25T23:25:20+03:00 false
tips
ffmpeg

Ищем устройство, которое отдаёт видео

Начну с далека...
Video4Linux (он же V4L) — коллекция драйверов для устройств и API для поддержки устройств захвата видео в реальном времени.
Драйвер поддерживает большенство USB веб-камер, TV тюнеров и связанных с ними устройств стандартизируя их выходные данные, чтобы легко добавлять поддержку видео в приложения.

В Linux есть утилита v4l2-ctl для работы с устройствами V4L. В Arch пакет v4l-utils.

Команда ниже выводит список поддерживаемых устройств.

v4l2-ctl --list-devices
Chicony USB 2.0 Camera: Chicony (usb-0000:00:1d.0-1.6):
        /dev/video0
        /dev/video1
        /dev/media0

Команда ниже выводит список поддерживаемых выходных форматов устройством.

v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YUYV' (YUYV 4:2:2)
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                Size: Discrete 352x288
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                Size: Discrete 320x240
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                Size: Discrete 176x144
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                Size: Discrete 160x120
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.125s (8.000 fps)

ffmpeg

ffmpeg -f v4l2 -framerate 30 -video_size 640x480 -i /dev/video0 -c copy output.mkv

Команда выше, получает видео из /dev/video0 и засовывет его в output.mkv.

Проще не куда, работает и хорошо.

Но что, если необходимо обрабатывать видео с камеры (добавлять фильтры/текст/изображения) и выводить результат в стрим, а не в файл?

Ранее для того, чтобы взять видео с камеры и отправить его в http использовался ffserver.

⚠️ ВНИМАНИЕ: Команда ниже не работает.

ffmpeg -s 600x480 -f video4linux2 -i /dev/video0 http://localhost:8000/camera.ffm

Но 2018-01-06 из ffmpeg был удалён ffserver.
Последний коммит, который содержал ffserver был 2ca65fc, по этому можно собрать и самому.

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg
git checkout 2ca65fc7b74444edd51d5803a2c1e05a801a6023
./configure
make -j4

Обсуждение на superuser.com.

ffmpeg -f v4l2 -s 352x288 -i /dev/video0 -filter_complex "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf: textfile=test.txt: y=25: x=25: fontcolor=red" -c:a copy http://localhost:8090/feed.ffm

Наложение текста на видео

Команда:

ffmpeg -f v4l2 -framerate 30 -video_size 640x480 -i /dev/video0 \
    -filter_complex "drawtext=fontfile=/home/user/.fonts/Ubuntu.ttf: text='ololo': y=25: x=25: fontcolor=red" \
    -c:v libx264 -c:a copy output.mkv

Здесь используется параметр ffmpeg -filter_complex со значением drawtext=....

Параметры в общем и целом понятны, объяснять не нужно.
Чтобы указать размер, необходимо дописать fontsize=40.

А если нужен стрим?... Легко!

ffmpeg -i /dev/video0 -v 0 -vcodec mpeg4 -f mpegts \
    -filter_complex "drawtext=fontfile=/home/user/.fonts/Windows\ 11/impact.ttf: text='ololo': fontsize=10: y=25: x=25: fontcolor=red" \
    udp://127.0.0.1:23000

Чтобы посмотреть результат, используем тег <video> или mpv.

mpv --profile=low-latency --untimed udp://127.0.0.1:23000

Параметры --profile=low-latency и --untimed необходимы, чтобы поток начал воспроизводиться с конца.

Без этих параметров будем получать ошибку Cannot seek in this stream.

Cannot seek in this stream.
You can force it with '--force-seekable=yes'.

А если использовать параметр --force-seekable=yes, будем получать ошибку first frame is no keyframe.

[ffmpeg/video] mpeg4: warning: first frame is no keyframe

И при попытке перемотать на конец потока, плеер будет возвращать воспроизведение на начало (нулевую секунду).