FFmpeg нарушает структуру while / if в скриптах Bash / shell - как это исправить? - PullRequest
0 голосов
/ 25 апреля 2020

Я пытаюсь извлечь определенное количество кадров из серии видео .mp4 в нескольких папках. Я читаю переменные из CSV-файла, где каждая строка CSV-файла содержит переменные для каждого клипа, а именно: «набор данных», «имя файла», «framelabel», «время начала клипа», «клип целевое время окончания »,« скорость извлечения »(в секундах на кадр) и« причина исключения ».

Я использую структуру while / if l oop, чтобы избежать попыток обработки видео, исключенных из нашего проекта.

Структура while / if l oop, кажется, хорошо работает, когда я просто распечатываю имена переменных. Однако, когда я вставляю строку кода ffmpeg, присваивание переменной для следующего видео (ie, следующая строка считывается из файла CSV) go haywire.

Вот код БЕЗ строки ffmpeg, которая, кажется, работает (все операторы "echo" просто там как средства отладки для отслеживания назначений переменных):

IFS=‘,’
while read DATASET FILENAME FRAMELABEL TARGET_START TARGET_END TOTAL_DURATION EXTRACT_RATE REASON_FOR_EXCLUSION 
do  
echo “PRE FFMPEG”
echo “dataset and filename are “ $DATASET/$FILENAME
echo “target start is “ $TARGET_START
echo “target end is “ $TARGET_END

if [ $TARGET_START != EXCLUDED ] && [ $TARGET_START != Target_start ]
then
IFS=‘:’ 
read -r -a fps_array <<< "$EXTRACT_RATE"
IFS=‘,’
let "secs = ${fps_array[0]}*3600 + ${fps_array[1]}*60 + ${fps_array[2]}"
FPS_RATE=$(echo "scale=20;1/$secs" | bc)

echo “AFTER FFMPEG”
echo “dataset and filename are “ $DATASET/$FILENAME
echo “target start is “ $TARGET_START
echo “target end is “ $TARGET_END

fi
done < Test_Key.csv`

Вывод для приведенного выше кода выглядит так, что это правильно (у меня есть 2 папки «cats» и «es123», по два видео в каждом; одно из видео es123 исключено из извлечения кадров):

“PRE FFMPEG”
“dataset and filename are “ cats/IMG_3460
“target start is “ 0:00:02
“target end is “ 0:00:24
“AFTER FFMPEG”
“dataset and filename are “ cats/IMG_3460
“target start is “ 0:00:02
“target end is “ 0:00:24
“PRE FFMPEG”
“dataset and filename are “ cats/IMG_4137
“target start is “ 0:00:10
“target end is “ 0:00:40
“AFTER FFMPEG”
“dataset and filename are “ cats/IMG_4137
“target start is “ 0:00:10
“target end is “ 0:00:40
“PRE FFMPEG”
“dataset and filename are “ es123/IMG_4577
“target start is “ EXCLUDED
“target end is “
“PRE FFMPEG”
“dataset and filename are “ es123/IMG_4839
“target start is “ 0:00:05
“target end is “ 0:00:25
“AFTER FFMPEG”
“dataset and filename are “ es123/IMG_4839
“target start is “ 0:00:05
“target end is “ 0:00:25

Однако затем я пытаюсь добавить свою строку ffmpeg, которая выполняет фактическое извлечение кадров:

IFS=‘,’
while read DATASET FILENAME FRAMELABEL TARGET_START TARGET_END TOTAL_DURATION EXTRACT_RATE REASON_FOR_EXCLUSION 
do  
echo “PRE FFMPEG”
echo “dataset and filename are “ $DATASET/$FILENAME
echo “target start is “ $TARGET_START
echo “target end is “ $TARGET_END

if [ $TARGET_START != EXCLUDED ] && [ $TARGET_START != Target_start ]
then
IFS=‘:’ 
read -r -a fps_array <<< "$EXTRACT_RATE"
IFS=‘,’
let "secs = ${fps_array[0]}*3600 + ${fps_array[1]}*60 + ${fps_array[2]}"
FPS_RATE=$(echo "scale=20;1/$secs" | bc)

ffmpeg -i $DATASET/$FILENAME.mp4 -ss $TARGET_START -to $TARGET_END -vf fps=$FPS_RATE ${DATASET}/${DATASET}_${FILENAME}_%03d.jpg

echo “AFTER FFMPEG”
echo “dataset and filename are “ $DATASET/$FILENAME
echo “target start is “ $TARGET_START
echo “target end is “ $TARGET_END

fi
done < Test_Key.csv

В результате кадры правильно извлекаются для первого mov ie, но затем имена переменных для второй mov ie полностью испорчен (и тогда, конечно, код не работает, потому что названия видео неверны). Вы можете увидеть это в выражениях 'echo', которые я использовал для отслеживания именования переменных, которые выглядят следующим образом:

“PRE FFMPEG”
“dataset and filename are “ cats/IMG_3460
“target start is “ 0:00:02
“target end is “ 0:00:24
“AFTER FFMPEG”
“dataset and filename are “ cats/IMG_3460
“target start is “ 0:00:02
“target end is “ 0:00:24
“PRE FFMPEG”
“dataset and filename are “ IMG_4839/es123_2
“target start is “ 0:00:25
“target end is “ 0:00:20

Кто-нибудь знает, почему ffmpeg влияет на функционирование структуры while / if l oop здесь? ? (Я довольно плохо знаком с сценариями оболочки, извините, если это что-то очевидно). И что я могу сделать, чтобы это исправить?

Спасибо!

Для справки, здесь все напечатано, когда я запускаю код с включенной строкой ffmpeg - появляются некоторые ошибки разбора, которые я не совсем понимаю, но, вероятно, объясни это.

“PRE FFMPEG”
“dataset and filename are “ cats/IMG_3460
“target start is “ 0:00:02
“target end is “ 0:00:24
ffmpeg version 4.2.2-tessus  https://evermeet.cx/ffmpeg/  Copyright (c) 2000-2019 the FFmpeg developers
  built with Apple clang version 11.0.0 (clang-1100.0.33.16)
  configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libmysofa --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvmaf --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-version3 --pkg-config-flags=--static --disable-ffplay
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'cats/IMG_3460.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
  Duration: 00:00:25.15, start: 0.000000, bitrate: 6866 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1080x1920, 6796 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
    Metadata:
      handler_name    : Core Media Video
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 69 kb/s (default)
    Metadata:
      handler_name    : Core Media Audio
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> mjpeg (native))
Press [q] to stop, [?] for help

Enter command: <target>|all <time>|-1 <command>[ <argument>]

Parse error, at least 3 arguments were expected, only 1 given in string 'ats,IMG_4137,cats_2,0:00:10,0:00:40,0:00:30,0:00:03,none,,'
[swscaler @ 0x7fd3fc953400] deprecated pixel format used, make sure you did set range correctly
Output #0, image2, to 'cats/cats_IMG_3460_%03d.jpg':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
    Stream #0:0(und): Video: mjpeg, yuvj420p(pc), 1080x1920, q=2-31, 200 kb/s, 0.50 fps, 0.50 tbn, 0.50 tbc (default)
    Metadata:
      handler_name    : Core Media Video
      encoder         : Lavc58.54.100 mjpeg
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
frame=    8 fps=3.2 q=1.6 size=N/A time=00:00:16.00 bitrate=N/A speed=6.33x    0.00 bitrate=N/A speed=6.59x    
Enter command: <target>|all <time>|-1 <command>[ <argument>]

Parse error, at least 3 arguments were expected, only 1 given in string 'LUDED,,,,boring,,'
frame=   11 fps=3.0 q=2.6 L00120000000000000000000000000000size=N/A time=00:00:22.00 bitrate=N/A speed=6.06x    
video:803kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
“AFTER FFMPEG”
“dataset and filename are “ cats/IMG_3460
“target start is “ 0:00:02
“target end is “ 0:00:24
“PRE FFMPEG”
“dataset and filename are “ IMG_4839/es123_2
“target start is “ 0:00:25
“target end is “ 0:00:20
-bash: let: secs = none*3600 + *60 + : syntax error: operand expected (error token is "*60 + ")
ffmpeg version 4.2.2-tessus  https://evermeet.cx/ffmpeg/  Copyright (c) 2000-2019 the FFmpeg developers
  built with Apple clang version 11.0.0 (clang-1100.0.33.16)
  configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libmysofa --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvmaf --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-version3 --pkg-config-flags=--static --disable-ffplay
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
IMG_4839/es123_2.mp4: No such file or directory
“AFTER FFMPEG”
“dataset and filename are “ IMG_4839/es123_2
“target start is “ 0:00:25
“target end is “ 0:00:20

1 Ответ

1 голос
/ 25 апреля 2020

Из руководства FFmpeg:

-stdin Включить взаимодействие на стандартном входе. Включено по умолчанию, если в качестве входа не используется стандартный ввод. Чтобы явно отключить взаимодействие, вам нужно указать «-nostdin».

В вашем случае достаточно передать -nostdin в CLI-файл FFmpeg pro c.

Если бы у вас было несколько циклов, вы могли бы также использовать разные FD, например:

while read DATASET FILENAME FRAMELABEL TARGET_START TARGET_END TOTAL_DURATION EXTRACT_RATE REASON_FOR_EXCLUSION  <&3 ;do 
...
done 3< Test_Key.csv 

Главное изменение здесь, конечно, 3.

...