Python автоматизировать преобразование ffmpeg из каталога загрузки - PullRequest
3 голосов
/ 23 января 2010

У меня есть скрипт загрузки. Но мне нужно выяснить, как создать сценарий, который я мог бы запускать как демон в python для обработки части преобразования и перемещения преобразованного файла в его окончательное место отдыха. Вот что у меня есть для скрипта наблюдателя каталога:

 #!/usr/bin/python

import os
import pyinotify import WatchManager, Notifier, ThreadedNotifier, ProcessEvent, EventCodes
import sys, time, syslog, config
from os import system
from daemon import Daemon

class myLog(ProcessEvent):
 def process_IN_CREATE(self, event):
  syslog.syslog("creating: " + event.pathname)
 def process_IN_DELETE(self, event):
  syslog.syslog("deleting: " + event.pathname)
 def process_default(self, event):
  syslog.syslog("default: " + event.pathname)

class MyDaemon(Daemon):
 def loadConfig(self):
  """Load user configuration file"""
  self.config = {}
  self.parser = ConfigParser.ConfigParser()
  if not os.path.isfile(self.configfile):
   self.parser.write(open(self.configfile, 'w'))
  self.parser.readfp(open(self.configfile, 'r'))

  variables = { \
   'mplayer':  ['paths', self.findProgram("mplayer")], \
   'mencoder':  ['paths', self.findProgram("mencoder")], \
   'tcprobe':  ['paths', self.findProgram("tcprobe")], \
   'transcode':  ['paths', self.findProgram("transcode")], \
   'ogmmerge':  ['paths', self.findProgram("ogmmerge")], \
   'outputdir':  ['paths', os.path.expanduser("~")], \
   }

  for key in variables.keys():
   self.cautiousLoad(variables[key][0], key, variables[key][1])

 def cautiousLoad(self, section, var, default):
  """Load a configurable variable within an exception clause,
  in case variable is not in configuration file"""
  try:
   self.config[var] = int(self.parser.get(section, var))
  except:
   self.config[var] = default
   try:
    self.parser.set(section, var, default)
   except:
    self.parser.add_section(section)
    self.parser.set(section, var, default)
   self.parser.write(open(self.configfile, 'w'))


 def findProgram(self, program):
  """Looks for program in path, and returns full path if found"""
  for path in config.paths:
   if os.path.isfile(os.path.join(path, program)):
    return os.path.join(path, program)
  self.ui_configError(program)

 def run(self):
  syslog.openlog('mediaConvertor', syslog.LOG_PID,syslog.LOG_DAEMON)
  syslog.syslog('daemon started, entering loop')
  wm = WatchManager()
  mask = IN_DELETE | IN_CREATE
  notifier = ThreadedNotifier(wm, myLog())
  notifier.start()
  wdd = wm.add_watch(self.config['outputdir'], mask, rec=True)
  while True:
   time.sleep(1)
  wm.rm_watch(wdd.values())
  notifier.stop()
  syslog.syslog('exiting media convertor')
  syslog.closelog()

if __name__ == "__main__":
 daemon = MyDaemon('/tmp/mediaconvertor.pid')
 if len(sys.argv) == 2:
  if 'start' == sys.argv[1]:
   daemon.run()
  if 'stop' == sys.argv[1]:
   daemon.stop()
  if 'restart' == sys.argv[1]:
   daemon.restart()
  else:
   print "Unknown Command"
   sys.exit(2)
  sys.exit(0)
 else:
  print "Usage: %s start|stop|restart" % sys.argv[0]
  sys.exit(2)

не уверен, куда идти.

1 Ответ

3 голосов
/ 24 января 2010

Я не работаю в Linux и никогда не использовал возможности inotify, которые вы используете здесь. Я опишу, как я буду делать вещи в общем.

В простейшем случае вам нужно проверить, есть ли новый файл в каталоге загрузки, и когда он есть, начните делать уведомление о преобразовании.

Чтобы проверить, есть ли новые файлы, вы можете сделать что-то вроде:

import os
import time

def watch_directory(dirname="."):
    old_files = set(os.listdir(dirname))
    while 1:
        time.sleep(1)
        new_files = set(os.listdir(dirname))
        diff = new_files - old_files
        if diff:
            print "New files", diff
        old_files = new_files

watch_directory()

Возможно, вы сможете минимизировать некоторые издержки файловой системы, предварительно указав каталог, чтобы увидеть, есть ли какие-либо изменения.

def watch_directory(dirname="."):
    old_files = set(os.listdir(dirname))
    old_stat = os.stat(dirname)
    while 1:
        time.sleep(1)
        new_stat = os.stat(dirname)
        if new_stat == old_stat:
            continue
        new_files = set(os.listdir(dirname))
        diff = new_files - old_files
        if diff:
            print "New files", diff
        old_stat = new_stat
        old_files = new_files

С inotify я думаю, что это все для вас, и вы помещаете свой код в process_IN_CREATE (), который вызывается, когда доступен новый файл.

Немного хитрости - откуда наблюдатель узнает, что загрузка завершена? Что произойдет, если загрузка будет отменена в процессе загрузки? Это может быть так же просто, как если бы веб-сервер выполнил переименование (), чтобы использовать одно расширение во время загрузки и другое расширение после завершения.

Как только вы знаете файл, используйте subprocess.Popen (Conversion_Program, "New_filename") или os.system ("Conversion_Program New_FileName &"), чтобы запустить преобразование в новом процессе, который выполняет преобразование. Вам нужно будет обрабатывать такие вещи, как отчеты об ошибках, например, когда ввод не в правильном формате. Он также должен очиститься, что означает, что после завершения преобразования он должен удалить входной файл из рассмотрения. Это может быть так же просто, как удалить файл.

Вам также нужно будет побеспокоиться о возобновлении любых конверсий, которые были убиты. Если машина не работает, как перезапущенный наблюдатель узнает, какие преобразования файлов данных также были уничтожены и должны быть перезапущены. Но это может быть выполнимо как ручной шаг.

...