PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/apps/projects/tasks.py

https://github.com/theinterned/batucada
Python | 103 lines | 74 code | 19 blank | 10 comment | 7 complexity | ad19fce3bcfb8b141e442466f048a50b MD5 | raw file
  1. import os
  2. import glob
  3. import logging
  4. import random
  5. import Image
  6. from django.conf import settings
  7. from celery.task import Task
  8. from drumbeat.utils import get_partition_id
  9. log = logging.getLogger(__name__)
  10. class ThumbnailGenerator(Task):
  11. def determine_path(self, project, filename):
  12. return "images/projects/%(partition)d/%(filename)s" % {
  13. 'partition': get_partition_id(project.pk),
  14. 'filename': filename,
  15. }
  16. def create_frames(self, media):
  17. """
  18. Using ffmpeg, extract one image per frame for the first n frames
  19. of a video file, where n is specified by the ``FFMPEG_VFRAMES``
  20. configuration variable.
  21. """
  22. working_dir = getattr(settings, 'FFMPEG_WD', '/tmp')
  23. abs_path = os.path.join(settings.MEDIA_ROOT, media.project_file.name)
  24. framemask = self.frame_prefix + ".%d.jpg"
  25. cmd = '%s -y -an -vframes %d -r 1 -i %s %s -v 1 > /dev/null 2>&1' % (
  26. self.ffmpeg, self.vframes, abs_path, framemask)
  27. os.chdir(working_dir)
  28. return_value = os.system(cmd)
  29. log.debug("Running command: %s" % (cmd,))
  30. if return_value != 0:
  31. log.warn("ffmpeg returned non-zero: %d" % (return_value,))
  32. return False
  33. return True
  34. def create_video_thumbnail(self, media):
  35. """
  36. Select a random frame from the video to use as the video thumbnail.
  37. """
  38. image = "%s.%d.jpg" % (self.frame_prefix,
  39. random.choice(range(1, self.vframes + 1)),)
  40. if not os.path.exists(image):
  41. log.warn("File %s does not exist!" % (image,))
  42. return
  43. thumbnail, ext = os.path.splitext(os.path.basename(image))
  44. thumbnail_filename = self.determine_path(
  45. media.project, "%s_thumbnail.png" % (thumbnail,))
  46. media.thumbnail = thumbnail_filename
  47. media.save()
  48. abs_path = os.path.join(settings.MEDIA_ROOT, thumbnail_filename)
  49. im = Image.open(image)
  50. im.thumbnail((128, 128), Image.ANTIALIAS)
  51. im.save(abs_path, 'PNG')
  52. return True
  53. def create_image_thumbnail(self, media):
  54. """Create a thumbnail for an image using PIL."""
  55. image = os.path.join(settings.MEDIA_ROOT, media.project_file.name)
  56. thumbnail_filename = self.determine_path(
  57. media.project, "%s_thumbnail.%s" % (os.path.splitext(
  58. os.path.basename(media.project_file.name))))
  59. thumbnail_path = os.path.join(settings.MEDIA_ROOT, thumbnail_filename)
  60. im = Image.open(image)
  61. im.thumbnail((128, 128), Image.ANTIALIAS)
  62. im.save(thumbnail_path, im.format)
  63. media.thumbnail = thumbnail_filename
  64. media.save()
  65. return True
  66. def run(self, media):
  67. self.ffmpeg = getattr(settings, 'FFMPEG_PATH', None)
  68. self.vframes = getattr(settings, 'FFMPEG_VFRAMES', 10)
  69. if not media.is_video():
  70. return self.create_image_thumbnail(media)
  71. if not self.ffmpeg:
  72. log.warn("No ffmpeg path set. Nothing to do.")
  73. return
  74. self.frame_prefix = "frame%d_%d" % (media.project.id, media.id)
  75. if not self.create_frames(media):
  76. log.warn("Error creating frames.")
  77. return
  78. if not self.create_video_thumbnail(media):
  79. log.warn("Error creating thumbnail")
  80. return
  81. # remove frame image files.
  82. files = glob.glob(self.frame_prefix + '*')
  83. for f in files:
  84. os.unlink(f)