149 lines
5.8 KiB
Markdown
149 lines
5.8 KiB
Markdown
|
---
|
|||
|
title: "🎥 Наложние текста на видео поток через ffmpeg"
|
|||
|
date: 2023-05-25T23:25:20+03:00
|
|||
|
draft: false
|
|||
|
tags: [tips, ffmpeg]
|
|||
|
---
|
|||
|
|
|||
|
## Ищем устройство, которое отдаёт видео
|
|||
|
|
|||
|
Начну с далека...
|
|||
|
**Video4Linux** (он же V4L) — коллекция драйверов для устройств
|
|||
|
и API для поддержки устройств захвата видео в реальном времени.
|
|||
|
Драйвер поддерживает большенство USB веб-камер, TV тюнеров и связанных с ними устройств
|
|||
|
стандартизируя их выходные данные, чтобы легко добавлять поддержку видео в приложения.
|
|||
|
|
|||
|
В Linux есть утилита `v4l2-ctl` для работы с устройствами V4L.
|
|||
|
В Arch пакет [v4l-utils](https://archlinux.org/packages/extra/x86_64/v4l-utils/).
|
|||
|
|
|||
|
Команда ниже выводит список поддерживаемых устройств.
|
|||
|
|
|||
|
```sh
|
|||
|
v4l2-ctl --list-devices
|
|||
|
```
|
|||
|
|
|||
|
```text
|
|||
|
Chicony USB 2.0 Camera: Chicony (usb-0000:00:1d.0-1.6):
|
|||
|
/dev/video0
|
|||
|
/dev/video1
|
|||
|
/dev/media0
|
|||
|
```
|
|||
|
|
|||
|
Команда ниже выводит список поддерживаемых выходных форматов устройством.
|
|||
|
|
|||
|
```sh
|
|||
|
v4l2-ctl --list-formats-ext
|
|||
|
```
|
|||
|
|
|||
|
```text
|
|||
|
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
|
|||
|
|
|||
|
```sh
|
|||
|
ffmpeg -f v4l2 -framerate 30 -video_size 640x480 -i /dev/video0 -c copy output.mkv
|
|||
|
```
|
|||
|
|
|||
|
Команда выше, получает видео из `/dev/video0` и засовывет его в `output.mkv`.
|
|||
|
|
|||
|
Проще не куда, работает и хорошо.
|
|||
|
|
|||
|
Но что, если необходимо обрабатывать видео с камеры
|
|||
|
(добавлять фильтры/текст/изображения) и выводить результат в стрим, а не в файл?
|
|||
|
|
|||
|
Ранее для того, чтобы взять видео с камеры и отправить его в http использовался `ffserver`.
|
|||
|
|
|||
|
⚠️ **ВНИМАНИЕ:** Команда ниже не работает.
|
|||
|
|
|||
|
```sh
|
|||
|
ffmpeg -s 600x480 -f video4linux2 -i /dev/video0 http://localhost:8000/camera.ffm
|
|||
|
```
|
|||
|
|
|||
|
Но 2018-01-06 из ffmpeg был удалён `ffserver`.
|
|||
|
Последний коммит, который содержал `ffserver` был `2ca65fc`, по этому можно собрать и самому.
|
|||
|
|
|||
|
```sh
|
|||
|
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
|
|||
|
cd ffmpeg
|
|||
|
git checkout 2ca65fc7b74444edd51d5803a2c1e05a801a6023
|
|||
|
./configure
|
|||
|
make -j4
|
|||
|
```
|
|||
|
|
|||
|
[Обсуждение](https://superuser.com/questions/1296377/why-am-i-getting-an-unable-to-find-a-suitable-output-format-for-http-localho)
|
|||
|
на superuser.com.
|
|||
|
|
|||
|
```sh
|
|||
|
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
|
|||
|
```
|
|||
|
|
|||
|
## Наложение текста на видео
|
|||
|
|
|||
|
Команда:
|
|||
|
|
|||
|
```sh
|
|||
|
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`.
|
|||
|
|
|||
|
**А если нужен стрим?... Легко!**
|
|||
|
|
|||
|
```sh
|
|||
|
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`.
|
|||
|
|
|||
|
```sh
|
|||
|
mpv --profile=low-latency --untimed udp://127.0.0.1:23000
|
|||
|
```
|
|||
|
|
|||
|
Параметры `--profile=low-latency` и `--untimed` необходимы,
|
|||
|
чтобы поток начал воспроизводиться с конца.
|
|||
|
|
|||
|
Без этих параметров будем получать ошибку `Cannot seek in this stream`.
|
|||
|
|
|||
|
```text
|
|||
|
Cannot seek in this stream.
|
|||
|
You can force it with '--force-seekable=yes'.
|
|||
|
```
|
|||
|
|
|||
|
А если использовать параметр `--force-seekable=yes`,
|
|||
|
будем получать ошибку `first frame is no keyframe`.
|
|||
|
|
|||
|
```text
|
|||
|
[ffmpeg/video] mpeg4: warning: first frame is no keyframe
|
|||
|
```
|
|||
|
|
|||
|
И при попытке перемотать на конец потока, плеер будет возвращать воспроизведение
|
|||
|
на начало (нулевую секунду).
|