1

I'd like some way to pipe the console output of ffplay to a bash script that parses it and isolates the current seek time and saves that number to a text file (I can put it in a RAM disk). It's so I can then grab that number and use it for an ad hoc quick and dirty editor I am making to stitch together rough cuts of stereoscopic gopro files without having to import the whole lot into a bloatware editor. So far my scripts work and it reads a file which has lists of file names and time stamps, but it's a lot of work cutting and pasting

I can easily make a bash script that builds this list, but I need a way to grab that number in real time whenever I hit a key in my other script

Anyone seen anything like this?

Ie pipe ffplay to script that grep / awk / sed / perl whatevers the frame time to a file?

0

Ok, I worked out a solution.

This is pretty crude, but is enough to show you how I did it.

As a bonus there is the ffprobe_parse function that you can also use to parse the output of ffprobe, to get the duration and frame rate, it happens to be the same format as the same information printed by ffplay, so I wrapped it in a function to make that part reusable.

#!/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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.