Below is an example of a python column provider for nautilus.
Identifying poor quality video files 480p, 720p … is difficult in nautilus at a glance.
You need to open the file properties to view the video metadata.
While there are a number of extensions out there for EXIF etc, i decided to implement my own.
Originally i tried to use MediaInfo, but it was far too slow. This is what i ended up with.
To activate it, just login and logout, or kill nautilus and restart it.
Create target directory and file
1 2 3 4 | mkdir -vp ~/.local/share/nautilus-python/extensions touch ~/.local/share/nautilus-python/extensions/VideoMetaData.py |
Install python libraries
1 2 3 4 5 | pip install hachoir-metadata pip install hachoir-parser pip install hachoir-core |
Add this to ~/.local/share/nautilus-python/extensions/VideoMetaData.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | #!/usr/bin/python # dave@fio.ie import os import urllib import logging import re import gi gi.require_version('Nautilus', '3.0') gi.require_version('Gtk', '3.0') from gi.repository import Nautilus, GObject, Gtk, Gdk, GdkPixbuf from hachoir_core.error import HachoirError from hachoir_core.stream import InputIOStream from hachoir_parser import guessParser from hachoir_metadata import extractMetadata class VideoMetadataExtension(GObject.GObject, Nautilus.ColumnProvider, Nautilus.MenuProvider, Nautilus.InfoProvider): def __init__(self): logging.basicConfig(filename='/tmp/VideoMetadataExtension.log',level=logging.DEBUG) pass def get_columns(self): return ( Nautilus.Column(name="NautilusPython::video_width_columnn",attribute="video_width",label="Width",description="Video width"), Nautilus.Column(name="NautilusPython::video_height_columnn",attribute="video_height",label="Height",description="Video height"), ) def update_file_info_full(self, provider, handle, closure, file_info): filename = urllib.unquote(file_info.get_uri()[7:]) video_width = '' video_height = '' name_suggestion = '' file_info.add_string_attribute('video_width', video_width) file_info.add_string_attribute('video_height', video_height) file_info.add_string_attribute('name_suggestion', name_suggestion) if file_info.get_uri_scheme() != 'file': logging.debug("Skipped: " + filename) return Nautilus.OperationResult.COMPLETE videomimes = [ 'video/x-msvideo', 'video/mpeg', 'video/x-ms-wmv', 'video/mp4', 'video/x-flv', 'video/x-matroska' ] for mime in videomimes: if file_info.is_mime_type(mime): GObject.idle_add(self.get_video_metadata, provider, handle, closure, file_info) logging.debug("in Progress: " + filename) return Nautilus.OperationResult.IN_PROGRESS logging.debug("Skipped: " + filename) return Nautilus.OperationResult.COMPLETE def get_video_metadata(self, provider, handle, closure, file_info): video_width = '' video_height = '' name_suggestion = '' filename = urllib.unquote(file_info.get_uri()[7:]) filelike = open(filename, "rw+") try: filelike.seek(0) except (AttributeError, IOError): logging.debug("Unabled to read: " + filename) Nautilus.info_provider_update_complete_invoke(closure, provider, handle, Nautilus.OperationResult.FAILED) return False stream = InputIOStream(filelike, None, tags=[]) parser = guessParser(stream) if not parser: logging.debug("Unabled to determine parser: " + filename) Nautilus.info_provider_update_complete_invoke(closure, provider, handle, Nautilus.OperationResult.FAILED) return False try: metadata = extractMetadata(parser) except HachoirError: logging.debug("Unabled to extract metadata: " + filename) Nautilus.info_provider_update_complete_invoke(closure, provider, handle, Nautilus.OperationResult.FAILED) return False if metadata is None: logging.debug("Metadata None: " + filename) Nautilus.info_provider_update_complete_invoke(closure, provider, handle, Nautilus.OperationResult.FAILED) return False matchObj = re.search( r'Image width: (.*?) pixels', str(metadata), re.M|re.I) if matchObj: video_width = matchObj.group(1) matchObj = re.search( r'Image height: (.*?) pixels', str(metadata), re.M|re.I) if matchObj: video_height = matchObj.group(1) file_info.add_string_attribute('video_width', video_width) file_info.add_string_attribute('video_height', video_height) file_info.add_string_attribute('name_suggestion', name_suggestion) logging.debug("Completed: " + filename) file_info.invalidate_extension_info() Nautilus.info_provider_update_complete_invoke(closure, provider, handle, Nautilus.OperationResult.COMPLETE) return False |
In detailed list view, have you managed to sort the rows according to the value of the new columns?
sorry for the slow reply.. i have looked into this yet.. its on my todo!
hi, did you manage to sort the new columns ? i’m trying to do it but I don’t know how ?