gpodder/share/gpodder/extensions/rockbox_convert2mp4.py

150 lines
5.3 KiB
Python

# -*- coding: utf-8 -*-
# Requirements: apt-get install python-kaa-metadata ffmpeg python-dbus
# To use, copy it as a Python script into ~/.config/gpodder/extensions/rockbox_mp4_convert.py
# See the module "gpodder.extensions" for a description of when each extension
# gets called and what the parameters of each extension are.
# Based on Rename files after download based on the episode title
# And patch in Bug https://bugs.gpodder.org/show_bug.cgi?id=1263
# Copyright (c) 2011-04-06 Guy Sheffer <guysoft at gmail.com>
# Copyright (c) 2011-04-04 Thomas Perl <thp.io>
# Licensed under the same terms as gPodder itself
import logging
import os
import shlex
import subprocess
import kaa.metadata
import gpodder
from gpodder import util
logger = logging.getLogger(__name__)
_ = gpodder.gettext
__title__ = _('Convert video files to MP4 for Rockbox')
__description__ = _('Converts all videos to a Rockbox-compatible format')
__authors__ = 'Guy Sheffer <guysoft@gmail.com>, Thomas Perl <thp@gpodder.org>, Bernd Schlapsi <brot@gmx.info>'
__category__ = 'post-download'
DefaultConfig = {
'device_height': 176.0,
'device_width': 224.0,
'ffmpeg_options': '-vcodec mpeg2video -b 500k -ab 192k -ac 2 -ar 44100 -acodec libmp3lame',
}
ROCKBOX_EXTENSION = "mpg"
EXTENTIONS_TO_CONVERT = ['.mp4', "." + ROCKBOX_EXTENSION]
FFMPEG_CMD = 'ffmpeg -y -i "%(from)s" -s %(width)sx%(height)s %(options)s "%(to)s"'
class gPodderExtension:
def __init__(self, container):
self.container = container
program = shlex.split(FFMPEG_CMD)[0]
if not util.find_command(program):
raise ImportError("Couldn't find program '%s'" % program)
def on_load(self):
logger.info('Extension "%s" is being loaded.' % __title__)
def on_unload(self):
logger.info('Extension "%s" is being unloaded.' % __title__)
def on_episode_downloaded(self, episode):
current_filename = episode.local_filename(False)
converted_filename = self._convert_mp4(episode, current_filename)
if converted_filename is not None:
util.rename_episode_file(episode, converted_filename)
os.remove(current_filename)
logger.info('Conversion for %s was successfully' % current_filename)
gpodder.user_extensions.on_notification_show(_('File converted'), episode.title)
def _get_rockbox_filename(self, origin_filename):
if not os.path.exists(origin_filename):
logger.info("File '%s' don't exists." % origin_filename)
return None
dirname = os.path.dirname(origin_filename)
filename = os.path.basename(origin_filename)
basename, ext = os.path.splitext(filename)
if ext not in EXTENTIONS_TO_CONVERT:
logger.info("Ignore file with file-extension %s." % ext)
return None
if filename.endswith(ROCKBOX_EXTENSION):
new_filename = "%s-convert.%s" % (basename, ROCKBOX_EXTENSION)
else:
new_filename = "%s.%s" % (basename, ROCKBOX_EXTENSION)
return os.path.join(dirname, new_filename)
def _calc_resolution(self, video_width, video_height, device_width, device_height):
if video_height is None:
return None
width_ratio = device_width // video_width
height_ratio = device_height // video_height
dest_width = device_width
dest_height = width_ratio * video_height
if dest_height > device_height:
dest_width = height_ratio * video_width
dest_height = device_height
return (int(round(dest_width)), round(int(dest_height)))
def _convert_mp4(self, episode, from_file):
"""Convert MP4 file to rockbox mpg file"""
# generate new filename and check if the file already exists
to_file = self._get_rockbox_filename(from_file)
if to_file is None:
return None
if os.path.isfile(to_file):
return to_file
logger.info("Converting: %s", from_file)
gpodder.user_extensions.on_notification_show("Converting", episode.title)
# calculationg the new screen resolution
info = kaa.metadata.parse(from_file)
resolution = self._calc_resolution(
info.video[0].width,
info.video[0].height,
self.container.config.device_width,
self.container.config.device_height
)
if resolution is None:
logger.error("Error calculating the new screen resolution")
return None
convert_command = FFMPEG_CMD % {
'from': from_file,
'to': to_file,
'width': str(resolution[0]),
'height': str(resolution[1]),
'options': self.container.config.ffmpeg_options
}
if gpodder.ui.win32:
p = util.Popen(shlex.split(convert_command))
p.wait()
stdout, stderr = ("<unavailable>",) * 2
else:
process = util.Popen(shlex.split(convert_command),
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
if process.returncode != 0:
logger.error(stderr)
return None
gpodder.user_extensions.on_notification_show("Converting finished", episode.title)
return to_file