Поврежденные файлы mpeg-4 при попытке поместить в сценарий запись и извлечение видеозаписей с экрана - PullRequest
0 голосов
/ 14 марта 2020

Я хочу написать скрипт, который запускает adb shell screenrecord в фоновом режиме моего скриптового цикла. Скрипт зацикливания будет ожидать в меню, ожидая, пока пользователь прочитает ввод из 1 символа.

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

Кроме того, мне нужно будет установить таймер обратного отсчета, который будет отображаться на экране после начала записи экрана, чтобы они знали, как близко они к 3-минутному пределу;

. .using printf "\r%*s" ((0)) "$remainingTime" в for l oop, например.

Это общая идея того, что я пытаюсь сделать:

fileName="rec.$$.mp4"

record(){
    adb shell screenrecord /sdcard/$fileName &

    read -n 1 -s -r -p ''

    #EOF represents where the screenrecord command expects the EOF signal
    EOF
}

extract(){
    adb pull sdcard/$fileName
}

record | wait && extract
exit

Использование этого метода для прерывание записи экрана (при замене EOF на return или kill "$childPID") может быть проблемой, но я нигде не могу найти, как выполнить sh прерывание EOF, чтобы избежать повреждения созданного видеофайла.

Прямо сейчас он прерывает с заменой EOF и также извлекает файл, но извлеченный файл всегда поврежден.

Есть идеи?

Я пытался добавить * 1 027 * и использует различные типы прерываний для замены сигнала EOF, но безрезультатно.

Это дает идентичные результаты; поврежденный видеофайл.

#!/bin/bash
set -x; clear

fileName="rec.$$.mp4"

record(){
    adb shell screenrecord /sdcard/$fileName & childPID=$!

    read -n 1 -s -r -p ''
    kill "$childPID"
    wait "$childPID"
}

extract(){
    adb pull sdcard/$fileName
}

record | wait && extract; exit

Замена команды kill на exit также дает идентичные результаты.

Ответы [ 2 ]

0 голосов
/ 15 марта 2020

Успех! После долгих проб и ошибок я нашел способ отправки eof в функцию screenrecord, выполняющуюся на оболочке устройства!

Решением было перехватить традиционные сигналы и заставить скрипт отправлять adb shell echo \04 всякий раз, когда Вызвана функция exitScript (обратите внимание, что это также функция, которая будет выполнять самые распространенные сигналы при перехвате).

#!/bin/bash
set -x; clear

fileName="rec.$$.mp4"

# make sure SIGINT always works even in presence of infinite loops
exitScript() {
    trap - SIGINT SIGTERM SIGTERM SIGSTOP # clear the trap
    adb shell echo \04; extract; exit
}; trap exitScript SIGINT SIGTERM SIGSTOP # set trap

record(){   
    adb shell screenrecord /sdcard/$fileName
}

extract(){
    adb pull sdcard/$fileName
}

record && extract
exitScript

Я также считаю, что отсутствие запуска screenrecord в подоболочке могло бы помочь избежать повреждения выходной файл.

После выполнения функции записи экрана l oop до тех пор, пока не произойдет прерывание (затем извлечение в фоновом режиме для непрерывных видеопоследовательностей) и помещения всего в функцию для подключения к моему сценарию, я думаю, что проблема полностью решен. Спасибо за вашу помощь!

#!/bin/bash

screenDVR(){
    clear
    read -r -p 'Enter the file path (or just drag the folder itself) of where you want to save the video sequences.. ' savePath
    if [ ! "$savePath" = "" ]; then cd ~; cd "$savePath"; else printf "\nDefaulting to home directory\n"; cd ~; fi

    # remove all files on device containing 'rec.'
    adb -d shell rm -f *"/sdcard/rec."*

    # make sure SIGINT always works even in presence of infinite loops
    exitScript() {
        trap - SIGINT SIGTERM SIGTERM # clear the trap
        tput cnorm
        adb -d shell echo \04; wait

        extract

        # remove all files on device containing 'rec.'
        adb -d shell rm -f *"/sdcard/rec."*; wait
        exit
    }; trap exitScript SIGINT SIGTERM # set trap

    extract(){
        printf "\n%*s\n" $((0)) "Extracting.. $fileName .. to your computer!"
        wait && adb pull sdcard/$fileName || return
    }

    record(){   
        printf "\n\n%*s\n\n" $((0)) "Use CTRL-C to stop the DVR.."
        while true; do
            tStamp="$(date +'%Hh%Mm%Ss')"
            fileName="rec.$tStamp.$$.mp4"

            printf "\n%*s\n\n" $((0)) "Starting new recording: $fileName"
            adb -d shell screenrecord /sdcard/$fileName || adb shell echo \04

            # running extract in a sub-process means the next video doesn't have any time-gap from the last
            wait; extract & continue
        done
    }
    record && wait && exitScript
}

(screenDVR) && printf "\ncontinue main loop\n"; exit
0 голосов
/ 14 марта 2020

После прочтения символа убейте фоновый процесс и дождитесь его завершения sh

fileName="rec.$$.mp4"
adb shell screenrecord /sdcard/"$fileName" &
childpid=$!
read -n 1 -s -r -p '' endRec
kill "$childpid"
wait "$childpid"
adb pull /sdcard/"$fileName"

Вместо того, чтобы использовать abd pull, просто передайте экранную запись в файл и сохраните ее на лету. .

fileName="rec.$$.mp4"
adb shell screenrecord - > "$fileName" &
childpid=$!
read -n 1 -s -r -p '' endRec
kill "$childpid"
wait "$childpid"

Я проверил, что, вручную вводя команду screenrecord и используя сигнал EOF для прерывания команды screenrecord,

Создаем fifo и отправляем его.

tmpd=$(mktemp -d)
fifo="$tmpd/fifo"
mkfifo "$fifo"
adb shell screenrecord /sdcard/"$fileName" < "$fifo" &
childpid=$!
read -n 1 -s -r -p '' endRec
echo -e '\04' > "$fifo"
wait "$childpid"
rm -r "$tmpd" # cleanup
adb pull /sdcard/"$fileName"

В качестве альтернативы здесь может пригодиться сопроцесс bash.

...