我希望能通过某种方式将 ffplay 的控制台输出传输到 bash 脚本,该脚本会解析它并隔离当前寻道时间并将该数字保存到文本文件(我可以将其放在 RAM 磁盘中)。这样我就可以获取该数字并将其用于我正在制作的临时快速编辑器,以便将立体 gopro 文件的粗略剪辑拼接在一起,而无需将所有内容导入到臃肿的编辑器中。到目前为止,我的脚本可以正常工作,它会读取包含文件名和时间戳列表的文件,但剪切和粘贴工作量很大
我可以轻松编写一个 bash 脚本来构建此列表,但我需要一种方法来在我按下其他脚本中的某个键时实时获取该数字
有人见过这样的事情吗?
即通过管道将 ffplay 传输到脚本,该脚本将 grep / awk / sed / perl 无论文件的帧时间是多少?
答案1
好的,我已经找到解决办法了。
这很粗糙,但足以向你展示我是怎么做的。
另外还有 ffprobe_parse 函数,您还可以使用它来解析 ffprobe 的输出,以获取持续时间和帧速率,它恰好与 ffplay 打印的相同信息格式相同,所以我将它包装在一个函数中以使该部分可重复使用。
#!/bin/bash
if [ ".$1" = "." ] ; then
echo "usage
$0 moviefilename "
exit 0
fi
QUIET=0
MOVIE="$1"
NOW_STAMP="$MOVIE.stamp.txt"
function ffprobe_parse {
VALID_STREAM=0
while read LINE
do
WORDS=($LINE)
CHECK=${WORDS[0]}
# Duration: 00:00:06.55, start: 0.008333, bitrate: 1068 kb/s
if [ "$CHECK" = "Duration:" ] ; then
IFS=',' read -ra PARSE_TEMP <<< "${WORDS[1]}"
DURATION_HHMMSS="${PARSE_TEMP[0]}"
IFS=':' read -ra HMS <<< "${DURATION_HHMMSS}"
DURATION_HH="${HMS[0]}"
DURATION_MM="${HMS[1]}"
DURATION_SS="${HMS[2]}"
DURATION_SECONDS=$(echo "($DURATION_HH * 3600.0) + ($DURATION_MM * 60.0) + $DURATION_SS" | bc)
echo "$DURATION_SECONDS" > "$MOVIE.duration.txt"
if [ "${WORDS[2]}" = "start:" ] ; then
IFS=',' read -ra PARSE_TEMP <<< "${WORDS[3]}"
PLAY_START_SECONDS="${PARSE_TEMP[0]}"
DURATION_SECONDS_ADJUSTED=$(echo "($DURATION_SECONDS - $PLAY_START_SECONDS)" | bc)
if [ $QUIET -eq 0 ] ; then
echo "offset start seconds is $PLAY_START_SECONDS"
echo "Total play duration is $DURATION_SECONDS_ADJUSTED seconds - $DURATION_HHMMSS minus $PLAY_START_SECONDS seconds"
fi
else
DURATION_SECONDS_ADJUSTED="$DURATION_SECONDS"
if [ $QUIET -eq 0 ] ; then
echo "Total play duration is $DURATION_SECONDS_ADJUSTED seconds"
fi
fi
# Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, smpte170m), 480x480, 1005 kb/s, 23.96 fps, 48.17 tbr, 600 tbn, 1200 tbc (default)
elif [ "$CHECK" = "Stream" ] ; then
VALID_STREAM=0
IFS=' ' read -ra PARSE_TEMP <<< "${LINE}"
for CHECK2 in "${PARSE_TEMP[@]}";
do
if [ "$CHECK2" = "Video:" ] ; then
VALID_STREAM=1
else
if [ "$CHECK2" = "Audio:" ] ; then
VALID_STREAM=0
else
if [ "$CHECK2" = "fps," ] && [ $VALID_STREAM -eq 1 ] ; then
FPS="$FPS_TEMP"
if [ $QUIET -eq 0 ] ; then
echo "detected stream fps: $FPS"
fi
break
fi
fi
FPS_TEMP="$CHECK2"
fi
done
if [ $VALID_STREAM -eq 1 ] ; then
IFS= read -r -d $'\r' ignore 2> /dev/null
break;
fi
fi
done
}
function ffplay_parse {
ffprobe_parse
if [ $QUIET -eq 0 ] ; then
echo "playing $DURATION_SECONDS seconds of video..."
fi
PERCENT_FUDGE=$(echo "$DURATION_SECONDS / 100" | bc -l)
while IFS= read -r -d $'\r' LINE
do
WORDS=($LINE)
STAMP=${WORDS[0]}
if [ "$STAMP" != "Seek" ] && [ "$STAMP" != "nan" ] && [ "${WORDS[1]}" != "@" ] ; then
if [ $(echo "$STAMP <= 0.0" | bc) -eq 1 ] ; then
STAMP=0.0
elif [ $(echo "$STAMP >= $DURATION_SECONDS" | bc) -eq 1 ] ; then
STAMP="$DURATION_SECONDS"
fi
PERCENT=$(echo "($STAMP / $PERCENT_FUDGE)" | bc)
echo $STAMP > $NOW_STAMP
if [ $QUIET -eq 0 ] ; then
echo -n $'\r' "Playing $MOVIE @ seconds = $STAMP, $PERCENT% of duration"
fi
fi
done
}
ffplay -i "$MOVIE" -window_title "Playing" 3>&1 1>&2 2>&3 | ffplay_parse &
MOVIE_PID=$!
if [ $QUIET -eq 0 ] ; then
echo "
Started player for $MOVIE, PID is $MOVIE_PID
You can use:
kill -9 $MOVIE_PID
to kill player.
"
fi
echo $MOVIE_PID > "$MOVIE.pid.txt"
if [ $QUIET -eq 0 ] ; then
wait $MOVIE_PID
echo ""
echo "Done"
fi
答案2
我有一个 Python 程序,每次按下暂停/播放按钮时,都会有 0.35 到 0.89 秒的开销。因此,之前播放时间的内部计算存在偏差。
使用这个答案从 shell 中(虽然尚未合并到脚本中)我可以使用:
$ ps aux | grep -v grep | grep ffplay
rick 16075 0.2 0.1 949956 45384 pts/22 Tl+ 09:28 0:02 ffplay -autoexit /media/rick/SANDISK128/Music/Alice Cooper/Welcome To My Nightmare/01 Welcome To My Nightmare.m4a -nodisp
$ sudo strace -p16075 -s9999 -e write
strace: Process 16075 attached
write(2, " 44.44 M-A: 0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.47 M-A: 0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.49 M-A: 0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.54 M-A: 0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.56 M-A: 0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.59 M-A: -0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.64 M-A: 0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.66 M-A: 0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.68 M-A: 0.000 fd= 0 aq= 23KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.72 M-A: -0.000 fd= 0 aq= 22KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.75 M-A: -0.000 fd= 0 aq= 22KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.77 M-A: 0.000 fd= 0 aq= 22KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
write(2, " 44.82 M-A: -0.000 fd= 0 aq= 21KB vq= 0KB sq= 0B f=0/0 \r", 69) = 69
^Cstrace: Process 16075 detached
第一个变量是经过的秒数,或者44.82在这种情况下。
相比之下,在 Python 程序中,暂停/播放被点击了十几次,计算出来的时间是53.31相差 8 秒半。
需要进行一些微调才能在strace
无需sudo
权限的情况下进行调用并仅在转储最后一行后退出。