Skip to content

Instantly share code, notes, and snippets.

@Palisand
Created January 9, 2022 00:46
Show Gist options
  • Save Palisand/5337aea19792e26548337e548096ee12 to your computer and use it in GitHub Desktop.
Save Palisand/5337aea19792e26548337e548096ee12 to your computer and use it in GitHub Desktop.
Old python code for transcoding images
"""
Helpers to transcode images.
DEPENDENCIES
------------
imagemagick (for converting, already installed)
avconv (for transcoding) sudo apt-get install libav-tools
libx264 (higher encoding quality) sudo apt-get install libavcodec-extra-53
http://askubuntu.com/questions/266663/ffmpeg-resize-could-not-find-codec-parameters
"""
from __future__ import absolute_import
import os
import time
import logging
import subprocess
from glob import glob
from tempfile import NamedTemporaryFile
from apps.services.aws.s3 import s3_bucket
from django.conf import settings
log = logging.getLogger(__name__)
STORAGE_DIR = '/percolate/hotlanta/apps/ugc/transcode/image/transcoded/'
def start_job(keyname, filename): # creator?
"""
Start a transcoding job using the given image file keyname
Args:
keyname (str) - key name of the image file to transcode
filename (str) - the name of the image file
"""
timestamp = str(time.time())
log.debug("native transcode job started for: " + keyname)
with s3_bucket(settings.S3_CLIENT_UPLOAD_BUCKET) as image_bucket, NamedTemporaryFile() as fp:
key = image_bucket.get_key(keyname)
key.get_contents_to_filename(fp.name)
f = os.path.splitext(os.path.basename(filename))[0]
if filename.endswith(".gif"):
# handle gif:
_convert_gif_to_mp4(fp.name, f)
_update_find_a_better_name() # store video on db + s3
else:
# handle img:
_convert_img_to_jpg(fp.name, f)
# replace img with jpg (db)
def _convert_gif_to_mp4(gif_path, mp4_name, quality=23):
"""
Converts a GIF to an MP4 and stores the result
Args:
gif_path (str) - the path to the gif file to convert
mp4_name (str) - the desired name of the resultant mpeg4 file
quality (int) - the desired quality of the resultant mpeg4 file
PLEASE NOTE:
Once Percolate updates to a more recent Ubuntu release, FFmpeg (the real one) can be used
and ALL of the code contained in this function can be substituted with one line, as follows:
subprocess.call('ffmpeg -i {0} -pix_fmt yuv420p -vf scale=trunc(iw/2)*2:trunc(ih/2)*2 \
{1}.mp4'.format(gif_path, mp4_name).split())
"""
ticks_per_frame = subprocess.check_output('identify -verbose -format %T_ {0}'.format(gif_path).split()).split('_')[:-1]
ticks_per_frame = [int(i) for i in ticks_per_frame]
num_frames = len(ticks_per_frame)
min_ticks = min(ticks_per_frame)
subprocess.call('convert -coalesce {0} tmp%d.png'.format(gif_path).split())
if len(set(ticks_per_frame)) > 1:
num_dup = 0
num_dup_total = 0
for frame, ticks in enumerate(ticks_per_frame):
num_dup_total += num_dup
frame += num_dup_total
num_dup = 0
if ticks > min_ticks:
num_dup = (ticks / min_ticks) - 1
for i in range(num_frames + num_dup_total - 1, frame, -1):
orig = 'tmp%d.png' % i
new = 'tmp%d.png' % (i + num_dup)
subprocess.call(['mv', orig, new])
for i in range(1, num_dup + 1):
curr = 'tmp%d.png' % frame
dup = 'tmp%d.png' % (i + frame)
subprocess.call(['cp', curr, dup])
framerate = (100 / min_ticks) if min_ticks else 10
subprocess.call('avconv -r {0} -i tmp%d.png -c:v libx264 -crf {1} -pix_fmt yuv420p \
-vf scale=trunc(iw/2)*2:trunc(ih/2)*2 -y {2}.mp4'.format(framerate, quality, STORAGE_DIR + mp4_name).split())
subprocess.call(['rm'] + glob('tmp*.png'))
def _convert_img_to_jpg(img_path, jpg_name):
"""
Converts an img file to a JPG and stores the result
Args:
img_file (str) - the path to the image file to convert
jpg_name (str) - the desired name of the resultant jpeg file
"""
# If this is going to remain a single line, might as well stick it in start_job
subprocess.call('convert {0} {1}.jpg'.format(img_path, STORAGE_DIR + jpg_name).split())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment