Я хочу написать скрипт, который одновременно отображает то, что на моей веб-камере, в окне на экране и записывает видео.

Вопрос или проблема

Я пробовал комбинацию:

  • v4l2loopback
  • ffmpeg
  • mpv

Но либо видео с веб-камеры, либо запись веб-камеры работает, но никогда не работает оба одновременно.

Может кто-нибудь предоставить скрипт, который этого добьется?

Вот что я попробовал до сих пор:

#!/usr/bin/env bash

set -x

# Это требует установки модуля видеопетли.
# sudo modprobe v4l2loopback devices=1 video_nr=10 card_label="VirtualCam" exclusive_caps=1

# используйте `pw-cli list-objects | grep node.name`, чтобы получить аудиоустройство
AUDIO_DEVICE="alsa_input.pci-0000_00_1f.3.analog-stereo"
VIDEO_DEVICE="/dev/video0"
VIRTUAL_VIDEO_DEVICE="/dev/video10"

read -p "Введите имя для видео: " VIDEO_NAME

if [ -z "$VIDEO_NAME" ]; then
    VIDEO_NAME="unnamed_video"
fi

OUTPUT_FILE="$HOME/videos/${VIDEO_NAME}_$(date +%Y%m%d_%H%M%S).mkv"

trap 'echo "Остановка записи..."; pkill -P $$; exit 0' SIGINT

ffmpeg -f v4l2 -framerate 30 -video_size 640x480 -i "$VIDEO_DEVICE" \
    -f v4l2 -video_size 640x480 -i "$VIRTUAL_VIDEO_DEVICE" &

sleep 2

# Начать отображение потока виртуальной веб-камеры с mpv
mpv --no-osc \
    --no-input-default-bindings \
    --profile=low-latency \
    --geometry=50%:50% \
    --autofit=100% \
    --input-conf=/dev/null \
    --title="WebcamDisplay" \
    --framedrop=no \
    --vf=scale=640:-1 \
    --vo=vaapi \
    "$VIRTUAL_VIDEO_DEVICE" &

# Начать запись с виртуального устройства с помощью ffmpeg
ffmpeg -f v4l2 -framerate 30 -video_size 640x480 -i "$VIRTUAL_VIDEO_DEVICE" \
    -f pulse -i "$AUDIO_DEVICE" \
    -c:v libx264 -preset ultrafast -crf 28 -pix_fmt yuv420p \
    -c:a aac -b:a 192k -ar 48000 \
    "$OUTPUT_FILE"

# Остановить все процессы после завершения
pkill ffmpeg
pkill mpv

Вот моя установка петли:

$ v4l2-ctl --list-devices
VirtualCam (platform:v4l2loopback-010):
        /dev/video10

Integrated_Webcam_HD: Integrate (usb-0000:00:14.0-12):
        /dev/video0
        /dev/video1
        /dev/media0

Вы на 90% на правильном пути. Вместо того чтобы пытаться считывать одно и то же устройство камеры (виртуальное или нет), просто добавьте другой вывод к вашему первому вызову ffmpeg.

Опции ffmpeg обычно имеют следующий формат:

ffmpeg {общие и входные опции} {опции для первого вывода} спецификация первого вывода {опции для второго вывода} спецификация второго вывода

ffmpeg -f v4l2 -i /dev/video0 -f v4l2 /dev/video10 -c:v libx264 out.mkv # | входные опции+спецификация | | вывод 1: нет -i !! | | вывод 2 |

Вы также можете включить свой аудиопоток в тот же момент; вот где -map в ffmpeg оказывается полезным: вы можете сопоставлять различные входные и выходные назначения.

Как указал @marcus-müller (https://unix.stackexchange.com/a/783282/663280), вы можете использовать ffmpeg, чтобы записывать выходной файл и поток к устройству петли. Измените первый вызов ffmpeg, чтобы он выглядел (похоже) так:

ffmpeg -f v4l2 -r 30 -video_size 640x480 -input_format mjpeg -i "$VIDEO_DEVICE" \
    -f pulse -i "$AUDIO_DEVICE" \
    -c:v copy -f v4l2 "$VIRTUAL_VIDEO_DEVICE" \
    -c:v libx264 -preset ultrafast -crf 28 -pix_fmt yuv420p \
    -c:a aac -b:a 192k -ar 48000 \
    "$OUTPUT_FILE" &

Относительно вашего оригинального вызова у нас есть:

  1. Добавлена -input_format mjpeg в первую строку, так как это то, что большинство (USB) веб-камер будут использовать для более высокого разрешения и более высокой частоты кадров (если используется что-то другое, например H264, конечно, укажите это здесь).
  2. Вставлен -f pulse -i "$AUDIO_DEVICE" после первой строки, чтобы подключить аудиоход.
  3. Выбрали ‘пропускать’ видео на устройство петли с помощью -c:v copy перед устройством (outfile).
  4. Вставлены строки для вывода на диск из вашего оригинального второго вызова к ffmpeg.
    • Примечание: используется кодек, установленный на H264 для вывода на диск через -c:v опцию перед именем файла (outfile).

Также нужно помочь mpv понять устройство петли. Я нашел следующий ресурс: https://github-wiki-see.page/m/mpv-player/mpv/wiki/Video4Linux2-Input.

Мы можем легко изменить ваш вызов mpv, чтобы получить правильный результат:

# Начать отображение потока виртуальной веб-камеры с mpv
mpv --no-osc \
    --no-input-default-bindings \
    --profile=low-latency \
    --untimed \
    --geometry=50%:50% \
    --autofit=100% \
    --input-conf=/dev/null \
    --title="WebcamDisplay" \
    --framedrop=no \
    --vf=scale=640:-1 \
    --vo=vaapi \
    "av://v4l2:$VIRTUAL_VIDEO_DEVICE"

По сравнению с вашим оригинальным вызовом:

  1. Мы добавили --untimed – что может быть полезно для потоков MJPEG (см. man mpv).
  2. Мы изменили имя файла, чтобы включить префикс av://v4l2: (опять же, большинство деталей доступно в man mpv).
  3. Теперь его больше не нужно отделять с помощью &.

Второй вызов ffmpeg должен быть удален.

В общем и целом:

#!/usr/bin/env bash

set -x

# Это требует установки модуля видеопетли.
# sudo modprobe v4l2loopback devices=1 video_nr=10 card_label="VirtualCam" exclusive_caps=1

# используйте `pw-cli list-objects | grep node.name`, чтобы получить аудиоустройство
AUDIO_DEVICE="alsa_input.pci-0000_00_1f.3.analog-stereo"
VIDEO_DEVICE="/dev/video0"
VIRTUAL_VIDEO_DEVICE="/dev/video10"

read -p "Введите имя для видео: " VIDEO_NAME

if [ -z "$VIDEO_NAME" ]; then
    VIDEO_NAME="unnamed_video"
fi

OUTPUT_FILE="$HOME/videos/${VIDEO_NAME}_$(date +%Y%m%d_%H%M%S).mkv"

trap 'echo "Остановка записи..."; pkill -P $$; exit 0' SIGINT

ffmpeg -f v4l2 -r 30 -video_size 640x480 -input_format mjpeg -i "$VIDEO_DEVICE" \
    -f pulse -i "$AUDIO_DEVICE" \
    -c:v copy -f v4l2 "$VIRTUAL_VIDEO_DEVICE" \
    -c:v libx264 -preset ultrafast -crf 28 -pix_fmt yuv420p \
    -c:a aac -b:a 192k -ar 48000 \
    "$OUTPUT_FILE" &

sleep 2

# Начать отображение потока виртуальной веб-камеры с mpv
mpv --no-osc \
    --no-input-default-bindings \
    --profile=low-latency \
    --untimed \
    --geometry=50%:50% \
    --autofit=100% \
    --input-conf=/dev/null \
    --title="WebcamDisplay" \
    --framedrop=no \
    --vf=scale=640:-1 \
    --vo=vaapi \
    "av://v4l2:$VIRTUAL_VIDEO_DEVICE"

# Остановить все процессы после завершения
pkill ffmpeg
pkill mpv

Ответ или решение

Создание скрипта для одновременной трансляции камеры и записи видео

Если вы хотите одновременно отображать картинку с веб-камеры в отдельном окне и записывать видео, сочетание инструментов ffmpeg, v4l2loopback, и mpv является отличным выбором. В этом руководстве приведён актуализированный и оптимизированный скрипт для достижения данной цели.

Исходные предпосылки

Перед тем как приступить к созданию скрипта, убедитесь, что у вас установлены необходимые пакеты и модули:

  1. Установка v4l2loopback: Убедитесь, что модуль v4l2loopback активирован. Используйте следующую команду для его загрузки:

    sudo modprobe v4l2loopback devices=1 video_nr=10 card_label="VirtualCam" exclusive_caps=1
  2. Установка FFmpeg: Если FFmpeg ещё не установлен, выберите подходящий способ установки, в зависимости от вашей операционной системы.

  3. Установка MPV: Убедитесь, что у вас установлен MPV для вывода изображения с веб-камеры.

Пример скрипта

Ниже представлен пример скрипта, который реализует вышеописанный функционал:

#!/usr/bin/env bash

set -x

# Аудио- и видеоустройства
AUDIO_DEVICE="alsa_input.pci-0000_00_1f.3.analog-stereo"  # Замените на ваше устройство
VIDEO_DEVICE="/dev/video0"  # Ваша веб-камера
VIRTUAL_VIDEO_DEVICE="/dev/video10"  # Виртуальная камера

# Запрос имени видеофайла
read -p "Введите имя для видео: " VIDEO_NAME
if [ -z "$VIDEO_NAME" ]; then
    VIDEO_NAME="unnamed_video"
fi

OUTPUT_FILE="$HOME/videos/${VIDEO_NAME}_$(date +%Y%m%d_%H%M%S).mkv"

# Обработка сигнала для остановки записи
trap 'echo "Остановлено."; pkill -P $$; exit 0' SIGINT

# Запуск FFmpeg для записи и вывода в виртуальную камеру
ffmpeg -f v4l2 -r 30 -video_size 640x480 -input_format mjpeg -i "$VIDEO_DEVICE" \
    -f pulse -i "$AUDIO_DEVICE" \
    -c:v copy -f v4l2 "$VIRTUAL_VIDEO_DEVICE" \
    -c:v libx264 -preset ultrafast -crf 28 -pix_fmt yuv420p \
    -c:a aac -b:a 192k -ar 48000 \
    "$OUTPUT_FILE" &

sleep 2

# Запуск MPV для отображения изображения с виртуальной камеры
mpv --no-osc \
    --no-input-default-bindings \
    --profile=low-latency \
    --untimed \
    --geometry=50%:50% \
    --autofit=100% \
    --input-conf=/dev/null \
    --title="WebcamDisplay" \
    --framedrop=no \
    --vf=scale=640:-1 \
    --vo=vaapi \
    "av://v4l2:$VIRTUAL_VIDEO_DEVICE"

# Остановка всех процессов при завершении
pkill ffmpeg
pkill mpv

Описание кода

  1. Переменные: Задаются переменные для аудио и видео устройств, а также для имени выходного файла.

  2. Обработка сигнала: При нажатии Ctrl+C выполняется остановка записи и выводится сообщение о завершении.

  3. Запуск FFmpeg:

    • Входные параметры: Указываются параметры для получения потока с веб-камеры и аудиопотока.
    • Выходные параметры: Видеопоток передаётся в виртуальную камеру, а также записывается в файл.
  4. Запуск MPV: После небольшой паузы запускается MPV для отображения контента с виртуальной камеры.

Заключение

Этот скрипт позволяет одновременно использовать веб-камеру для трансляции и записи видео, что может быть полезно для различных задач, таких как создание обучающих материалов или прямые эфиры. Настройка и запуск такого решения требуют базовых знаний в области работы с Linux, но это прозрачное решение позволит вам легко начать работать с вашим видеопотоком.

Оцените материал
Добавить комментарий

Капча загружается...