Thumbnails of Topfield REC Videos in File Manager
Thumbnails of Topfield REC videos in file manager.
Mplayer-video-thumbnailer allows nautilus to create thumbnails of weird video formats. It probably supports all formats available in Mplayer. With some GConf settings, it can thumbnail “.REC”, Topfield DVB recorder native MPEG-2 format for recorded TV.
I (Tero) just wrote GConf schema and the patch. Mplayer-video-thumb is written by Ravinder Rathi and others, MPlayer is written by Árpád Gereöffy and others.
Testing
On Ubuntu 9.04 64bit, mplayer-video-thumb-1.4-1.tar.bz2 + my patch.
$ head -c 25 tayskaannos.rec ; echo TFrcP0aka $ mplayer-video-thumb.py tayskaannos.rec tayskaannos.png File not found: " /usr/share/totem/flim-role.png ". Thumbnailing without film stripe background. Removing TMP dir $ file tayskaannos.png tayskaannos.png: PNG image, 128 x 96, 8-bit/color RGB, non-interlaced
Viewing the thumbnail file in gqview shows it’s correct.
Patch: Better error handling
Print better error messages. Without patch “Something gone wrong”, with patch: “Something gone wrong: [Errno 2] No such file or directory: ‘/usr/share/totem/flim-role.png’“.
Works without film stripe background image “flim-role.png”.
Patch copyright 2009 Tero Karvinen http://iki.fi/karvinen GNU General Public License version 2 or later
=== modified file 'mplayer-video-thumb.py' --- mplayer-video-thumb.py 2009-11-21 21:28:04 +0000 +++ mplayer-video-thumb.py 2009-11-21 21:48:16 +0000 @@ -17,7 +17,8 @@ # John Conroy <jconroy@gmail.com> # Stephen Kennedy <stevek@gnome.org> # Fedora Fat <?> -# Bittu <?> +# Bittu <?> +# Tero Karvinen http://iki.fi/karvinen # # All rights reserved. # @@ -40,6 +41,7 @@ from tempfile import mkdtemp from random import randint import time, select, signal +import os.path Size="128" #default thumbnail size -really-quiet Role="/usr/share/totem/flim-role.png" TMP=mkdtemp('',"mvideothumb.","/tmp/") @@ -162,18 +164,23 @@ else: frame=TMP+"/00000014.jpg" f=Image.open(frame) - r=Image.open(Role) - rr=r.resize((f.size)) - f.paste(rr,(0,0),rr) + + if os.path.exists(Role): + r=Image.open(Role) + rr=r.resize((f.size)) + f.paste(rr,(0,0),rr) + else: + print "File not found: \"", Role, "\". Thumbnailing without film stripe background." f.save(OFile,"PNG") else: print "Taking too much time" runMplayer.kill() - except: - print "Something gone wrong" + #except: + except Exception, err: + print "Something gone wrong:", err pass print "Removing TMP dir" - rmtree(TMP) + rmtree(TMP) Instructions = "This script genrate thumbnail of video file \n"+\ "e.g.: python mplayer-video-thumb.py -s size input output \n"+\
Registering Gnome/Nautilus thumbnailer for .REC
GConf Schema for REC
<?xml version="1.0"?>
<gconfschemafile>
<schemalist>
<schema>
<key>/schemas/desktop/gnome/thumbnailers/application@x-extension-rec/enable</key>
<applyto>/desktop/gnome/thumbnailers/application@x-extension-rec/enable</applyto>
<owner>mplayer-video-thumb</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short/>
<long/>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/thumbnailers/application@x-extension-rec/command</key>
<applyto>/desktop/gnome/thumbnailers/application@x-extension-rec/command</applyto>
<owner>mplayer-video-thumb</owner>
<type>string</type>
<default>mplayer-video-thumb.py -s %s %u %o</default>
<locale name="C">
<short/>
<long/>
</locale>
</schema>
</schemalist>
</gconfschemafile>
Install with Gconftool
# Makefile for mplayer-video-thumb.py # (c) 2009 Tero Karvinen http://www.iki.fi/karvinen # GNU General Public License, version 2 or later install: gconftool-2 --install-schema-file rec-topfield-mplayer-video-thumb-schema.xml
Makefile does not install the executable, mplayer-video-thumbnailer. Put it anywhere in the path, such as /usr/local/bin.
Sample run:
gconftool-2 --install-schema-file rec-topfield-mplayer-video-thumb-schema.xml Attached schema `/schemas/desktop/gnome/thumbnailers/application@x-extension-rec/enable' to key `/desktop/gnome/thumbnailers/application@x-extension-rec/enable' Installed schema `/schemas/desktop/gnome/thumbnailers/application@x-extension-rec/enable' for locale `C' Attached schema `/schemas/desktop/gnome/thumbnailers/application@x-extension-rec/command' to key `/desktop/gnome/thumbnailers/application@x-extension-rec/command' Installed schema `/schemas/desktop/gnome/thumbnailers/application@x-extension-rec/command' for locale `C'
Whole sourcecode for mplayer-video-thumbnailer
#!/usr/bin/env python # # FILE: mplayer-video-thumb.py -- A script to generate PNG thumbnails # from MPlayer playable video files for use by Nautilus... # # Examples: # mplayer-video-thumb.py -s 128 file:///home/user/video.avi /home/user/thumb.png # # # Requirements: # mplayer - MPlayer Project ( http://www.mplayerhq.hu/ ) # Python Python Image Module # # Last Updated: 18 December 2006 # # Written By: Ravinder Rathi <mes030581@gmail.com> # John Conroy <jconroy@gmail.com> # Stephen Kennedy <stevek@gnome.org> # Fedora Fat <?> # Bittu <?> # Tero Karvinen http://iki.fi/karvinen # # All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import sys,os,Image,subprocess from shutil import rmtree from urllib import unquote from tempfile import mkdtemp from random import randint import time, select, signal import os.path Size="128" #default thumbnail size -really-quiet Role="/usr/share/totem/flim-role.png" TMP=mkdtemp('',"mvideothumb.","/tmp/") CMD="nice -n 10 /usr/bin/mplayer -nojoystick -nolirc -nortc -noautosub -framedrop -noconsolecontrols -nomouseinput -nocache -ni -nobps -nodouble -nograbpointer -vf scale -nosound -zoom -nostop-xscreensaver -nofs -nokeepaspect -monitorpixelaspect 1 -vo jpeg:outdir="+TMP+":quality=100 -slave -x " #Follwing Python unix subprocess wrapper by PIAdraig Brady (http://code.activestate.com/recipes/576387/) class subProcess: """Class representing a child process. It's like popen2.Popen3 but there are three main differences. 1. This makes the new child process group leader (using setpgrp()) so that all children can be killed. 2. The output function (read) is optionally non blocking returning in specified timeout if nothing is read, or as close to specified timeout as possible if data is read. 3. The output from both stdout & stderr is read (into outdata and errdata). Reading from multiple outputs while not deadlocking is not trivial and is often done in a non robust manner.""" def __init__(self, cmd, bufsize=8192): """The parameter 'cmd' is the shell command to execute in a sub-process. If the 'bufsize' parameter is specified, it specifies the size of the I/O buffers from the child process.""" self.cleaned=False self.BUFSIZ=bufsize self.outr, self.outw = os.pipe() self.errr, self.errw = os.pipe() self.pid = os.fork() if self.pid == 0: self._child(cmd) os.close(self.outw) #parent doesn't write so close os.close(self.errw) # Note we could use self.stdout=fdopen(self.outr) here # to get a higher level file object like popen2.Popen3 uses. # This would have the advantages of auto handling the BUFSIZ # and closing the files when deleted. However it would mean # that it would block waiting for a full BUFSIZ unless we explicitly # set the files non blocking, and there would be extra uneeded # overhead like EOL conversion. So I think it's handier to use os.read() self.outdata = self.errdata = '' self._outeof = self._erreof = 0 def _child(self, cmd): # Note sh below doesn't setup a seperate group (job control) # for non interactive shells (hmm maybe -m option does?) os.setpgrp() #seperate group so we can kill it os.dup2(self.outw,1) #stdout to write side of pipe os.dup2(self.errw,2) #stderr to write side of pipe #stdout & stderr connected to pipe, so close all other files map(os.close,[self.outr,self.outw,self.errr,self.errw]) try: cmd = ['/bin/sh', '-c', cmd] os.execvp(cmd[0], cmd) finally: #exit child on error os._exit(1) def read(self, timeout=None): """return 0 when finished else return 1 every timeout seconds data will be in outdata and errdata""" currtime=time.time() while 1: tocheck=[] if not self._outeof: tocheck.append(self.outr) if not self._erreof: tocheck.append(self.errr) ready = select.select(tocheck,[],[],timeout) if len(ready[0]) == 0: #no data timeout return 1 else: if self.outr in ready[0]: outchunk = os.read(self.outr,self.BUFSIZ) if outchunk == '': self._outeof = 1 self.outdata += outchunk if self.errr in ready[0]: errchunk = os.read(self.errr,self.BUFSIZ) if errchunk == '': self._erreof = 1 self.errdata += errchunk if self._outeof and self._erreof: return 0 elif timeout: if (time.time()-currtime) > timeout: return 1 #may be more data but time to go def kill(self): os.kill(-self.pid, signal.SIGTERM) #kill whole group def cleanup(self): """Wait for and return the exit status of the child process.""" self.cleaned=True os.close(self.outr) os.close(self.errr) pid, sts = os.waitpid(self.pid, 0) if pid == self.pid: self.sts = sts return self.sts def __del__(self): if not self.cleaned: self.cleanup() def mkthumb( Size,IFile,OFile ): try: if (IFile[:7] == "file://"): IFile=IFile[7:] if (os.path.getsize(IFile) < 200000): cmd=CMD+str(Size)+" -y "+str((int(Size)*96)/128)+" -frames 2" else: Seek=randint(15,70) cmd="echo seek "+str(Seek)+" 1 | "+CMD+str(Size)+" -y "+str((int(Size)*96)/128)+" -frames 14" #os.system('%s "%s"' % (cmd,IFile)) #runMplayer=subprocess.Popen(('%s "%s"' % (cmd,IFile)),shell=True) #runMplayer.wait() runMplayer = subProcess(('%s "%s"' % (cmd,IFile))) if (runMplayer.read(5) == 0): #Wait for at max 5 sec for geting frames if (os.path.getsize(IFile) < 200000): frame=TMP+"/00000002.jpg" else: frame=TMP+"/00000014.jpg" f=Image.open(frame) if os.path.exists(Role): r=Image.open(Role) rr=r.resize((f.size)) f.paste(rr,(0,0),rr) else: print "File not found: \"", Role, "\". Thumbnailing without film stripe background." f.save(OFile,"PNG") else: print "Taking too much time" runMplayer.kill() #except: except Exception, err: print "Something gone wrong:", err pass print "Removing TMP dir" rmtree(TMP) Instructions = "This script genrate thumbnail of video file \n"+\ "e.g.: python mplayer-video-thumb.py -s size input output \n"+\ "e.g.: python mplayer-video-thumb.py input output \n"+\ "default size is 128" if __name__=="__main__": if len(sys.argv) == 5: mkthumb(sys.argv[2],unquote(sys.argv[3]),sys.argv[4]) elif len(sys.argv) == 3: mkthumb(Size,unquote(sys.argv[1]),sys.argv[2]) else: print Instructions
See also
Video thumbnails with Mplayer
hikaricore 2006: Howto: Video Thumbnails for .BIN & .RM Files. http://ubuntuforums.org/archive/index.php/t-278162.html This article has example schema for installing mplayer-video thumb to Gnome as Nautilus thumbnailer.
Rathi: Video Thumbnailer For Gnome - Mplayer-video-thumb http://sites.google.com/site/me20305812/
Programming and Standards
Hellmann: Python Exception Handling Techniques http://www.doughellmann.com/articles/Python-Exception-Handling/index.html
Gnome contributors: Installing a Thumbnailer Program http://library.gnome.org/devel/integration-guide/stable/thumbnailer.html.en