• The forum software that supports hummy.tv has been upgraded to XenForo 2.3!

    Please bear with us as we continue to tweak things, and feel free to post any questions, issues or suggestions in the upgrade thread.

Thumbnails - any configuration?

An excellent implementation af123. I tried it out last night, and it works a treat.

Thanks for another really useful feature!
 
The thumbnail generator seems to be having problems with a file containing crops. Is this because the .nts is then out of sync with the .ts? Is the correct work-flow to set the thumbnail before doing any cropping?
 
The NTS should be synced up ok but it's likely that the timecodes in the final .ts file aren't zero based causing ffmpeg to have problems finding the right timestamp. If I'm right you'll see similar problems with timeshifted recordings too..
 
What happened is that I cropped out the advert breaks (not something I bother to do very often, but this is intended for passing on), then in the result decided that a frame going into the advert break would be a good thumbnail. When the thumbnail generator produced its sample frames, only 1 and 5 had anything in them, 2 3 and 4 were just grey - and I wondered if they were somehow inside the removed section. I tried a few variations before and after, but its knickers were in a right twist.
 
I haven't done any cropping and I've found that about 5% - 10% of recordings won't set a thumbnail in this way.
I think it's something to do with timestamps.

If I use different options for ffmpeg I can generate thumbnails for these files but that involves decoding every frame from the start to the thumbnail.
This takes approx real-time for SD broadcasts (so setting a thumbnail at 5mins in takes about 5 minutes) and much longer for HD broadcasts.
 
The below script is what I am now using to auto-generate thumbnails.
I have had this running as a cron job (every 30 minutes) for a few days and it seems to work really well.
I find it quite satisfying to have the thumbnails reflect the actual recording rather than an advert/trailer/previous programme.

A few notes;

1. It ignores in-use, audio and encrypted files
2. It flags a thumbnail as processed by changing the 4th byte from FF to FE (not sure if WebIF thumbnail function flags the files in any way)
3. It falls back to a slower method for SD files if there is a problem (set slowForSD to "0" to disable this)
4. The only issue I have with it that it doesn't seem to read the next file name properly after an ffmpeg operation (something to do with buffers?). However the next time it runs it will be fine (as it does not re-process any files)
5. The ffmpeg logging output can be massive (I think just for the slow mode) so I would suggest not appending to a log file if using this.


Code:
targetTime="400"
slowForSD="1"
 
cd /
cd "media/My Video"
find . -type f -name "*.ts" | while read fileTS
do
        file=${fileTS#*/}
    fileRoot=${file%.ts}
    process="0"
 
        inuse "$file"
       
        if [ $? == "0" ]
        then
            echo "xx "`date +"%d-%m %H:%M"`" In use $file"
        else
        if [ -f "$fileRoot.thm" ]
        then
        checkByte=`hexdump -n1 -s3 -e'"" 1/1 "%02x"' "$fileRoot.thm"`
        if [ $checkByte == "ff" ]
        then
            process="1"
        fi
        else
        process="1"
        fi
       
 
          if [ $process == "1" ]
        then
                flags=`hmt "$fileRoot.hmt" | grep -o 'Flags: .*$'`
               
                markFile="1"
                if [ "${flags/*ODEncrypted*}" == "" ]
                then
                    echo "xx "`date +"%d-%m %H:%M"`" Encrypted $file"
                    markFile="0"
                else
                    videoID=`hmt "$fileRoot.hmt" | grep -o 'Video PID:.*$'`
                    videoID=${videoID#Video PID}
                    audioID=`hmt "$fileRoot.hmt" | grep -o 'Audio PID:.*$'`
                    audioID=${audioID#Audio PID}
               
            if [ $audioID == $videoID ]
            then
                echo "xx "`date +"%d-%m %H:%M"`" $file is audio only"
            else
           
                ffmpeg -loglevel quiet -ss "$targetTime" -i "$file" -frames 1 -pix_fmt bgra -vf vflip -s 140x78 TempThumb.bmp
                        if [ ! -f TempThumb.bmp ]
                        then
                            echo "xx "`date +"%d-%m %H:%M"`" $file requires slow capture"
                            if [ "${flags/*SD*}" == "" ] && [ $slowForSD == "1" ]
                            then
                                echo "-- "`date +"%d-%m %H:%M"`" Attempting slow capture $file"
                                ffmpeg -loglevel quiet -i "$file" -ss "$targetTime" -frames 1 -an -pix_fmt bgra -vf vflip -s 140x78 TempThumb.bmp
                            fi
                        else
                            echo "++ "`date +"%d-%m %H:%M"`" Thumbnail created $file"
                        fi
                    fi
               
                    if [ -f TempThumb.bmp ]
                    then
                dd bs=54 skip=1 if=TempThumb.bmp of="$fileRoot.thm"
                rm TempThumb.bmp
            fi
       
            if [ -f "$fileRoot.thm" ] && [ $markFile == "1" ]
            then
                echo -ne \\xFE | dd conv=notrunc bs=1 count=1 seek=3 of="$fileRoot.thm"
            fi
        fi
            else
                echo "-- "`date +"%d-%m %H:%M"`" Already processed $file"
        fi
    fi   
done
 
2. It flags a thumbnail as processed by changing the 4th byte from FF to FE (not sure if WebIF thumbnail function flags the files in any way)
As far as I know the existing WebIF thumbnail generator distinguishes generated thumbnail files from Humax standard ones by appending an extra byte. This means the difference can be read from the file properties without actually reading the file at all.
 
How do other DVRs (eg TOPPY) treat thumbnails on recordings. Do they use the first frame. Or could there be some sort of thumbnail flag that the recordings point to a predetermined frame on a recording. If this was so and the hummy is not detecting it.

Do mp4 files have thumbnails like embedded jpg files? On the hummy the mp4 file has no thumbnail just a greyed out icon. MP4 files converted to avi files automatically generate a more appropriate thumbnail-like .jpg file. Curious!
 
How do other DVRs (eg TOPPY) treat thumbnails on recordings. Do they use the first frame. Or could there be some sort of thumbnail flag that the recordings point to a predetermined frame on a recording. If this was so and the hummy is not detecting it.

Do mp4 files have thumbnails like embedded jpg files? On the hummy the mp4 file has no thumbnail just a greyed out icon. MP4 files converted to avi files automatically generate a more appropriate thumbnail-like .jpg file. Curious!

I don't understand your point. The thumbnail is in a specific file <recording>.thm which is generated by the Humax from the recording, either when you first play the file or on the first boot after the recording was made. As standard, the Humax just takes the first frame of the recording. The WebIF thumbnail generator simply provides an alternative means to select a frame and generate a .thm file from it, and replace the standard file (if it exists). The Humax doesn't try to create a .thm if one already exists (although there can be a problem if it is in the process of creating one, so measures are taken to circumvent it).

There are no markers or embedded thumbnails, and the Humax only looks for a .thm if the recording is a .ts and (I think) the .hmt exists. It doesn't check for a .mp4. One could, if one so desired, copy in a standard frame as the .thm, creating icons for specific recordings - another function for classifier perhaps.
 
I suppose my point was about the creation of the .thm file. If you were designing a process to create a thumbnail for a recording would you automatically use the first frame? Perhaps using a frame 77 seconds in may be more appropriate.
 
To be honest I dont know what my point is. From what you say, and I read on threads the 'ts' container contains 4 files and the .thm file is the thumbnail. Other PVRs (e.g. Topfield) dont create thumbnails.

And if you are going to create a thumbnail would it not make sense that the thumbnail would be specific for a program/series just as the prid/crid is.
 
And if you are going to create a thumbnail would it not make sense that the thumbnail would be specific for a program/series just as the prid/crid is.
Yes, in which case the programme maker or broadcaster should generate an icon for it.
Maybe a future Freeview update will include that function so the PVRs can pick it up (but not on Channel 5 - obviously :rolleyes: ).
 
From what you say, and I read on threads the 'ts' container contains 4 files and the .thm file is the thumbnail.
Just to clarify, the .ts file is a container for the data streams (video, audio, subtitle, etc) which may themselves be encoded in a variety of formats, and then the .ts container format defines how these streams are packaged up into one file. Similar applies to other container formats (mp4, mkv, etc). The thumbnail is NOT part of this package.

The Humax (specifically) creates a file set, the usual set being .ts, .hmt, .nts, and .thm (there are variations, for example a radio recording does not have a .thm, and a "naked" .ts get another file added if you play it but I don't recall what it's called*). The thumbnail is one of the files in this set (.thm), not part of the .ts container.

* see post 117
 
I really don't understand why they decided to use the first frame for the thumbnail. I use AR so all my thumbnails just show the channel splashscreen - i don't know what else they thought would happen. It would have made more sense to me if they picked a frame say a minute in.
 
I agree that there is no way to predict the "right" thumbnail, but it can be a lot better than the default.

Below is my latest script for auto generating thumbnails based on a given time into the video.
It generally generates a thumbnail that is recognisably for the recorded programme.
Try it and see what you think. I am very pleased with it.

This has several enhancements from the last version:
  • Doesn't overwrite web-if generated thumbnails
  • Checks for all grey thumbnails and uses the fallback behaviour
  • Added lower target time for HD recordings fallback
  • Fixed the issues with buffers affecting the list of files to process
  • Disabled all logging of ffmpeg
  • Defaulted to only logging actions (not status checks etc.)
  • Runs any pending auto tasks (e.g. decryption) before creating thumbnails
  • Check for a command line argument of STANDBY and use the ir package to shutdown the Humax.
The last two items I added so it can be run overnight.
I was seeing some picture breakup on recordings which I think were caused by the CPU load of ffmpeg operations.
Now I set my Humax to turn on at 06:00 and my script runs at 06:01 and shuts down the Humax when finished

The options are all at the top of the script so they can easily be changed.
targetTime - number of seconds into the recording to capture the image (I have 2 minutes pre-padding so 400 generally works)
hdTargetFallback - if HD thumbnail generation fails, try again with this alternate target time (should be less than the original targetTime)
slowForSD - if SD thumbnail generation fails, set to 1 to use a slow capture that is more accurate (otherwise set to 0)
logActionsOnly - if you want more detailed logging (e.g. file already processed, audio only file etc.) change this to 0

Code:
targetTime="400"
hdTargetFallback="200"
slowForSD="1"
logActionsOnly="1"
 
if [ $logActionsOnly == "0" ]
then
    echo "  "`date +"%d-%m %H:%M"`" Running auto task"
fi
/mod/webif/lib/bin/auto
 
cd /
cd "media/My Video"
find . -type f -name "*.ts" | while read fileTS
do
        file=${fileTS#*/}
    fileRoot=${file%.ts}
    process="0"
 
        inuse "$file"
     
        if [ $? == "0" ]
        then
            if [ $logActionsOnly == "0" ]
            then
                echo "xx "`date +"%d-%m %H:%M"`" In use $file"
            fi
        else
        if [ -f "$fileRoot.thm" ]
        then
        checkByte=`hexdump -n1 -s3 -e'"" 1/1 "%02x"' "$fileRoot.thm"`
                fileSize=$(stat -c '%s' "$fileRoot.thm")
 
        if [ $checkByte == "ff" ] && [ $fileSize == "43680" ]
        then
            process="1"
        fi
        else
        process="1"
        fi
     
 
          if [ $process == "1" ] && [ -f "$fileRoot.hmt" ]
        then
                flags=`hmt "$fileRoot.hmt" | grep -o 'Flags: .*$'`
             
                markFile="1"
                if [ "${flags/*ODEncrypted*}" == "" ]
                then
                    if [ $logActionsOnly == "0" ]
                    then
                        echo "xx "`date +"%d-%m %H:%M"`" Encrypted $file"
                    fi
                    markFile="0"
                else
                    videoID=`hmt "$fileRoot.hmt" | grep -o 'Video PID:.*$'`
                    videoID=${videoID#Video PID}
                    audioID=`hmt "$fileRoot.hmt" | grep -o 'Audio PID:.*$'`
                    audioID=${audioID#Audio PID}
             
            if [ $audioID == $videoID ]
            then
                if [ $logActionsOnly == "0" ]
                then
                    echo "xx "`date +"%d-%m %H:%M"`" $file is audio only"
                fi
            else
         
                cat /dev/null | ffmpeg -loglevel quiet -ss "$targetTime" -i "$file" -frames 1 -pix_fmt bgra -vf vflip -s 140x78 TempThumb.bmp > /dev/null 2>&1
                     
                        attemptSlowCapture="0"
                        if [ ! -f TempThumb.bmp ]
                        then
                            attemptSlowCapture="1"
                        else
                            picStart=`hexdump -s 54 -n 32 -v -e'"" 1/1 "%02x"' TempThumb.bmp`
                            if [ $picStart == "818181ff818181ff818181ff818181ff818181ff818181ff818181ff818181ff" ]
                            then
                                echo "xx "`date +"%d-%m %H:%M"`" $file thumb looks faulty"
                                attemptSlowCapture="1"
                            fi                     
                        fi
 
                        if [ $attemptSlowCapture == "1" ]
                        then
                            echo "xx "`date +"%d-%m %H:%M"`" $file requires slow capture"
                            if [ "${flags/*SD*}" == "" ] && [ $slowForSD == "1" ]
                            then
                                echo "-- "`date +"%d-%m %H:%M"`" Attempting slow capture $file"
                             
                                cat /dev/null | ffmpeg -loglevel quiet -i "$file" -r 25 -ss "$targetTime" -frames 1 -an -pix_fmt bgra -vf vflip -s 140x78 TempThumb.bmp > /dev/null 2>&1
                            else
                                echo "-- "`date +"%d-%m %H:%M"`" Attempting HD fallback thumbnail $file"
                                cat /dev/null | ffmpeg -loglevel quiet -ss "$hdTargetFallback" -i "$file" -r 25 -frames 1 -an -pix_fmt bgra -vf vflip -s 140x78 TempThumb.bmp > /dev/null 2>&1
                            fi
                        else
                            echo "++ "`date +"%d-%m %H:%M"`" Thumbnail created $file"
                        fi
                    fi
             
                    if [ -f TempThumb.bmp ]
                    then
                dd bs=54 skip=1 if=TempThumb.bmp of="$fileRoot.thm" > /dev/null 2>&1
                rm TempThumb.bmp
            fi
     
            if [ -f "$fileRoot.thm" ] && [ $markFile == "1" ]
            then
                echo -ne \\xFE | dd conv=notrunc bs=1 count=1 seek=3 of="$fileRoot.thm" > /dev/null 2>&1
            fi
        fi
            else
                if [ $logActionsOnly == "0" ]
                then
                    if [ -f "$fileRoot.hmt" ]
                    then
                        echo "-- "`date +"%d-%m %H:%M"`" Already processed $file"
                    else
                        echo "-- "`date +"%d-%m %H:%M"`" No media information for $file"
                    fi
                fi
        fi
    fi
 
done
 
if [ "$1" == "STANDBY" ]
then
    if [ $logActionsOnly == "0" ]
    then
        echo "  "`date +"%d-%m %H:%M"`" Shutting down"
    fi
    ir STANDBY >> /dev/null
fi
 
Back
Top