FFmpeg: Записать экран, но помните только последние 5 минут?
Я использую Ffmpeg для непрерывной записи видео с экрана на моем ПК. Тем не менее, мне нужны последние 5 минут видео.
Да, я мог бы отредактировать видео позже. Но эти сеансы записи могут продолжаться в течение нескольких часов и занимать много места на жестком диске.
Есть ли способ запомнить только последние 5 минут захвата видео и забыть все предыдущее до сохранения файла? (Вроде как сделал бы TiVO)
я обнаружил
-fs limit_size
а также
-timelimit duration
... но они, кажется, прекращаются, как только предел достигнут. Может быть, есть обратный переключатель? Как сохранить только последние 1000000 байтов или что-то.
2 ответа
Спасибо user704244 за правильный трек.
Это заняло много времени, но я понял, что кажется действительно эффективным способом сделать это.
Альтернативы
Наивным решением был бы круговой буфер . Это может быть возможно, но это, безусловно, не кажется практичным, поскольку я ничего не могу сделать в Интернете.
Вы также можете каким-то образом удалить данные из начала файла, когда он становится слишком длинным, но я не думаю, что это возможно, пока файл записывается.
Ответ @Sepero - отличный обходной путь, но я действительно хотел иметь возможность в конечном итоге включать аудио, поэтому я изучил полностью собственное решение ffmpeg.
Вот тут и появляется формат ffmpeg.
Концепция
Допустим, мы хотим сохранить только последние 5 секунд данных.
Идея состоит в том, что мы записываем данные за 5 секунд в файл A , а затем начинаем записывать следующие 5 секунд в файл B. Когда мы достигаем 10 секунд, мы начинаем перезаписывать следующие 5 секунд в файл A (поскольку у нас уже есть последние 5 секунд в файле B ) и так далее. У нас всегда будут последние 5 секунд в любом из двух файлов, и у нас будет максимум 10 секунд накладных расходов. Это избавляет нас от необходимости хранить часы записи экрана только для того, чтобы обрезать последние N секунд/минут.
После того, как у нас есть два сегмента, мы можем объединить их в один файл <= 10 секунд. Затем мы можем обрезать последние 5 секунд из этого файла.
Я использую Windows 11 и версию ffmpeg n4.3.1-29.
1. Запись экрана на сегменты
Это будет постоянно записывать ваш рабочий стол с помощью gdigrab и передавать этот ввод в сегмент. Сегмент создаст два файла с именами segment0.mp4 и segment1.mp4, а также файл catfile.ffcat, который поможет их объединить позже.
Вы можете остановить эту команду, нажав Ctrl+ cили набрав q, а затем enter.
ffmpeg -y -f gdigrab -video_size 1920x1080 -show_region 1 -i desktop \
-f segment -segment_time 300 -segment_format mp4 -segment_list catfile.ffcat \
-segment_wrap 2 -reset_timestamps 1 segment%d.mp4
Я не эксперт по ffmpeg, но попытаюсь объяснить, что делает каждая часть команды:
2. Объедините сегменты вместе
После того, как мы создали два фрагмента, мы можем легко объединить их в один файл, используя наш файл cat, созданный в предыдущей команде.
Я не знаю тонкостей этого, но
ffmpeg -y -i catfile.ffcat -map 0 -c copy combined.mp4
3. Получите последние 5 минут
Обрежьте последние 5 минут. Как я уже сказал, у нас есть видео, которое гарантированно длится от 5 до 10 минут, поэтому у нас не должно возникнуть проблем с обрезкой последних 5 минут.
ffmpeg -y -sseof -300 -i combined.mp4 output.mp4
4. Удалите временные файлы
Вам нужно будет самостоятельно удалить эти лишние файлы после операции. Вы можете запустить:
rm catfile.ffcat segment0.mp4 segment1.mp4 combined.mp4
Очень многословный ответ, но мне очень хотелось, чтобы у меня было что-то подобное, когда я искал, поэтому я надеюсь, что эти знания помогут кому-то еще!
Я согласен, что я хотел бы видеть эту функцию в ffmpeg.
В качестве обходного решения я создал скрипт для записи экрана на изображения и непрерывного удаления старых изображений. К сожалению, это не сохраняет аудио. Вот сценарий.
#!/bin/bash
set -e -u
mkdir "$HOME/history" || true
rm "$HOME"/history/img*.png || true
# Get screen resolution.
RES="$(xwininfo -root | grep -Po 'geometry[^+]*' | sed 's/^\S* //')"
# Record the screen into images into /home/username/history/ one per second.
avconv -s "$RES" -f x11grab -i :0.0 -r 1 -f image2 "$HOME/history/img%06d.png" &
AVCONV_PID=$!
trap "kill $AVCONV_PID" INT TERM EXIT
while true; do
# Delete screen images older than 5 minutes.
find "$HOME/history" -name "img*.png" -mmin +5 -exec rm {} +
sleep 10
done
Если вы хотите 5 кадров в секунду, измените часть -r 1
в -r 5
, Посмотрите эту ссылку, как собрать изображения в видео (avi, mpeg) файл.
PS.
Вы также можете использовать ffmpeg вместо avconv.