Rescuing a Truncated Recording Using ffmpeg

tl;dr: Well, it’s cheating because it’s not ‘rescuing’ what isn’t recorded, just retrieving and appending

Last night I played a few rounds of some cooperative gameplay with some good friends, and as usual I recorded the session for posterity.

Hans Volter's on fire and about to die
“Oh man, oh god!”, Hans is about to croak.

However, when looking over the file created, neither VLC nor ffmpeg could determine a duration. I used ffmpeg to create a new file (ffmpeg -i old.mkv -c copy new.mkv), and when it got to about the 1 hour 50 minute mark in the stream copy, it printed the following error:

invalid return value 0 for stream protocol
[matroska,webm @ 0x55eb60b609c0] Read error
Invalid return value 0 for stream protocol

It’s possible that I ran out of space during recording, so it behoves me to make sure my disks are more clear — hopefully the process of migrating to a combined fileserver will help there! — before I start recording.

Fortunately, I also stream to Twitch and so I could create a ‘highlight’ of the latter part of gameplay- about 45 minutes’ worth. The quality isn’t as good (max bitrate 3500kbit), but it’s better than nothing. So that it can be seamlessly appended, I decided to upscale the size from 720p to 1080p using ffmpeg:

$ ffmpeg -i ~/downloads/211006613-69819912-48eb80ad-009f-42d5-83aa-f68dda7b7612.mp4 -vf scale=1920x1080:flags=lanczos
-c:a copy -crf 20 -preset slow ~/mounts/storage/video/2017-12-19\ 22-04-59b.mkv

frame=105361 fps= 24 q=28.0 size= 2402802kB time=00:29:16.20 bitrate=11208.1kbits/s speed=0.408x

(Conversion in progress! Using -vf scale=1920x1080:flags=lanczos to scale and -crf 20 to ensure quality stays reasonable)

After that, it should be a simple matter of using the concat demuxer, assuming the files are similar enough (both are pixel format yuvj420p)– I previously had issues when trying to create an auto-highlighter/clip creator that minimised re-encoding.

For posterity!

Timesaver: import and combine GoPro Footage with FFmpeg

I’ve been taking my GoPro to Sunday Morning Football (as it is known) for a while now, so I figured I’d automate the process of importing the footage (moving it from microSD) and combining it into one file (GoPro splits recordings by default).

So I have the following script:


DATE="$(date +%Y-%m-%d)"

if [ -e $GOPRO ]; then
        echo "Copying..."
        rsync -aP --info=progress2 --remove-source-files --include='*.MP4' $GOPRO/DCIM/100GOPRO/ $VIDEO_DEST/
        echo "Joining..."
        cd $VIDEO_DEST
        #cd $GOPRO/DCIM/100GOPRO/
        for file in `ls *.MP4`; do echo "file '$file'" >> stitch.txt; done
        #RECORD_DATE="$(ffprobe -v quiet `ls *.MP4 | head -n1` -show_entries stream=index,codec_type:stream_tags=creation_time:format_tags=creation_time | grep creation_time | head -n1| cut -d '=' -f 2| cut -d ' ' -f1)"
        # new format:
        RECORD_DATE="$(ffprobe -v quiet `ls *.MP4 | head -n1` -show_entries stream=index,codec_type:stream_tags=creation_time:format_tags=creation_time | grep creation_time | head -n1| cut -d '=' -f 2| cut -d ' ' -f1| cut -d 'T' -f1)"
        #echo "$RECORD_DATE"
        ffmpeg -y -f concat -i stitch.txt -c copy $RECORD_DATE.mp4
        echo "GoPro microSD not mounted?"


  • the microSD is already mounted before running (under /tmp/gopro) – I had considered automating this, but I figured running a script in response to insertion of removable media was a bad idea; I could add the mkdir and mount commands here, but since the latter requires root privileges I’d rather not and it is quickly recalled from bash history in any case
    • the $VIDEO_BASE directory is mounted and created (this is pretty stable)
    • the GoPro won’t number directories higher than 100GOPRO (eg 101GOPRO)- it possibly would if dealing with eg timelapse, but I am not covering that case
    • the GoPro will set creation time correctly; so far it has reset to the default date a few times, probably related to battery
    • I want to keep the source files around after creation (the script could remove them)

Given the above the script may seem a bit fragile – and it is definitely tightly coupled to my assumptions – but it’s done the job for a few weeks at least, and the commands it was based on have been pretty stable since I started recording football last year.

Extract A Single Image From A Video Using FFMPEG

Dead handy, this:

ffmpeg -ss 0.5 -i inputfile.mp4 -t 1 -s 480x300 -f image2 imagefile.jpg

The various options:

  • -t 1: limit to 1 frame extracted
  • -ss 0.5: point of movie to extract from (ie seek to 0.5 seconds)
  • -s 480x300: frame size of image to output (image resized to fit dimensions)
  • -f image2: forces format

I use this to generate preview stills for jwplayer to use. Dead handy!

Edit: Thanks to reader DieBagger who pointed out it is much faster to place the seek argument before the input file.