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

149 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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
```
И при попытке перемотать на конец потока, плеер будет возвращать воспроизведение
на начало (нулевую секунду).