16 июля 2009 г.

Информация о медиафайлах

В недавнем посте об отображении тегов mp3-файлов рассказывалось об утилите mp3info. К сожалению, она обладает существенными недостатками: не понимает ID3v2 и работает, как следует из названия, только с mp3-файлам.

Однако, сама по себе утилитка довольно удобна. Поэтому я решил написать небольшой скрипт, предоставляющий похожий интерфейс, но понимающий большее количество медиаформатов.

Естественно, писал я его не на пустом месте. Для работы скрипта потребуется библиотека Kaa.Metadata:
sudo aptitude install python-kaa-metadata

Параметров у скрипта всего два (для простоты): форматная строка и файл (или несколько файлов через пробел):
mediainfo.py ФОРМАТ файл(ы)

При указании файла можно использовать стандартные шаблоны. Так что вполне допустимо имя вида «*.mp3». Можно использовать и более сложные шаблоны: «~/Музыка/*/*.mp3».

Скрипт не умеет рекурсивно обходить каталоги, но это ему и не нужно. Обход можно реализовать, например, средствами bash.

Подробнее о форматной строке. В ней можно использовать следующие шаблоны:
%t — название,
%a — исполнитель,
%r — частота дискретизации,
%l — продолжительность,
%m — продолжительность (только минуты),
%s — продолжительность (только секунды)
%c — кодек,
%b — битрейт,
%n — номер трека,
%A — альбом,
%g — жанр,
%% — символ %.

В ней также можно использовать обычные питоновские экранированные последовательности: \n, \t и т. д.

Вставлять \n в конце форматной строки не нужно, это делается автоматически. Кроме того, вывод скрипта автоматически переконвертируется в кодировку текущей локали.

Если теги файла записаны в однобайтовой кодировке и формат тегов не предусматривает указания кодировки, то скорее всего вместо ожидаемой cp1251 будет latin-1. Впрочем, ответственность за это лежит на библиотеке. Может, это можно настроить, я глубоко не вникал. Во всяком случае, это еще один повод перевести все теги в utf-8.

Утилиту можно использовать как саму по себе, так и в конвейере:
mediainfo.py '%l' ~/Музыка/*/* | awk '{s += $1} END {print "≈",int(s/3600),"hour(s)"}'

А вот, собственно, исходный текст скрипта:
#!/usr/bin/env python
#-*- coding:utf-8 -*-

# Disable all warnings
import warnings
warnings.filterwarnings('ignore')

# Disable log messages
#import logging
#logger = logging.getLogger('metadata')
#logger.setLevel(logging.CRITICAL)

# Get locale encoding
import locale
encoding = locale.getdefaultlocale()[1]

import os
import sys
import glob
import string
import kaa.metadata

class MyTemplate(string.Template): delimiter = '%'

def addItem(infolist, info):
item = {}
item['t'] = info.title # Title
item['a'] = info.artist # Artist
item['r'] = info.samplerate # Samplerate
item['l'] = int(info.length) # Length (seconds)
item['m'] = int(item['l'] / 60) % 60 # Length (minutes only)
item['s'] = format(item['l'] % 60, '02d') # Length (seconds only)
item['c'] = info.codec # Codec
item['b'] = info.bitrate # Bitrate
item['n'] = info.trackno # Track number
item['A'] = info.album # Album title
item['g'] = info.genre # Genre
infolist.append(item)

def process(path):
infolist = []
path = os.path.normpath(path)
for f in glob.glob(os.path.expanduser(path)):
if os.path.isdir(f):
continue
try:
info = kaa.metadata.parse(f)
except:
info = None
if info != None:
addItem(infolist, info)
return infolist

if len(sys.argv) < 3:
print 'Usage:'
print os.path.split(sys.argv[0])[1], 'FORMAT file(s)'
exit(0)
for f in sys.argv[2:]:
infolist = process(f)
for item in infolist:
sys.stdout.write(MyTemplate(sys.argv[1]).safe_substitute(item).encode(encoding) + '\n')

Не забываем разрешить его выполнение:
chmod +x mediainfo.py

Комментариев нет:

Отправить комментарий