Skip to content

Instantly share code, notes, and snippets.

@tomdyson
Created July 17, 2013 16:19
Show Gist options
  • Save tomdyson/6022098 to your computer and use it in GitHub Desktop.
Save tomdyson/6022098 to your computer and use it in GitHub Desktop.
Use Zencoder to convert mp4 files into HTTP Live segments and playlist, e.g. to meet Apple's requirements for iOS video streaming apps.
# Check an FTP directory for new files, send any to Zencoder for
# conversion to HTTPLive playlists, tell Zencoder to put converted files
# in FTP or S3
# Installation:
# pip install zencoder
# Usage:
# Add S3 credentials to Zencoder - https://app.zencoder.com/account/credentials
# Configure Zencoder, S3 and FTP details
# python rsa-zencoder.py
from zencoder import Zencoder
from ftplib import FTP
# Access details
ZENCODER_API_KEY = ''
ZENCODER_CREDENTIALS = '' # the label you assign your S3 credentials to, in Zencoder's admin UI
FTP_USER = ''
FTP_PASS = ''
FTP_HOST = ''
FTP_DIR = ''
FTP_SOURCE_URL= 'ftp://%s:%s@%s/cds/IPOD/' % (FTP_USER, FTP_PASS, FTP_HOST)
ZENCODER_DESTINATION_URL = 's3://your-bucket-name.s3.amazonaws.com/'
ENCODED_DB = '/var/encoded-videos.db'
def make_outputs(base_url):
# generate segments and playlist recommended by Zencoder
# https://app.zencoder.com/docs/guides/encoding-settings/http-live-streaming
outputs = [
{
"audio_bitrate": 56,
"audio_sample_rate": 22050,
"base_url": base_url,
"credentials": ZENCODER_CREDENTIALS,
"filename": "file-64k.m3u8",
"format": "aac",
"public": 1,
"type": "segmented"
},
{
"audio_bitrate": 56,
"audio_sample_rate": 22050,
"base_url": base_url,
"credentials": ZENCODER_CREDENTIALS,
"decoder_bitrate_cap": 300,
"decoder_buffer_size": 800,
"filename": "file-240k.m3u8",
"max_frame_rate": 15,
"public": 1,
"type": "segmented",
"video_bitrate": 200,
"width": 400,
"format": "ts"
},
{
"audio_bitrate": 56,
"audio_sample_rate": 22050,
"base_url": base_url,
"credentials": ZENCODER_CREDENTIALS,
"decoder_bitrate_cap": 600,
"decoder_buffer_size": 1600,
"filename": "file-440k.m3u8",
"public": 1,
"type": "segmented",
"video_bitrate": 400,
"width": 400,
"format": "ts"
},
{
"audio_bitrate": 56,
"audio_sample_rate": 22050,
"base_url": base_url,
"credentials": ZENCODER_CREDENTIALS,
"decoder_bitrate_cap": 900,
"decoder_buffer_size": 2400,
"filename": "file-640k.m3u8",
"public": 1,
"type": "segmented",
"video_bitrate": 600,
"width": 480,
"format": "ts"
},
{
"audio_bitrate": 56,
"audio_sample_rate": 22050,
"base_url": base_url,
"credentials": ZENCODER_CREDENTIALS,
"decoder_bitrate_cap": 1500,
"decoder_buffer_size": 4000,
"filename": "file-1040k.m3u8",
"public": 1,
"type": "segmented",
"video_bitrate": 1000,
"width": 640,
"format": "ts"
},
{
"audio_bitrate": 56,
"audio_sample_rate": 22050,
"base_url": base_url,
"credentials": ZENCODER_CREDENTIALS,
"decoder_bitrate_cap": 2250,
"decoder_buffer_size": 6000,
"filename": "file-1540k.m3u8",
"public": 1,
"type": "segmented",
"video_bitrate": 1500,
"width": 960,
"format": "ts"
},
{
"audio_bitrate": 56,
"audio_sample_rate": 22050,
"base_url": base_url,
"credentials": ZENCODER_CREDENTIALS,
"decoder_bitrate_cap": 3000,
"decoder_buffer_size": 8000,
"filename": "file-2040k.m3u8",
"public": 1,
"type": "segmented",
"video_bitrate": 2000,
"width": 1024,
"format": "ts"
},
{
"base_url": base_url,
"credentials": ZENCODER_CREDENTIALS,
"filename": "playlist.m3u8",
"public": 1,
"streams": [
{
"bandwidth": 2040,
"path": "file-2040k.m3u8"
},
{
"bandwidth": 1540,
"path": "file-1540k.m3u8"
},
{
"bandwidth": 1040,
"path": "file-1040k.m3u8"
},
{
"bandwidth": 640,
"path": "file-640k.m3u8"
},
{
"bandwidth": 440,
"path": "file-440k.m3u8"
},
{
"bandwidth": 240,
"path": "file-240k.m3u8"
},
{
"bandwidth": 64,
"path": "file-64k.m3u8"
}
],
"type": "playlist"
}
]
return outputs
# What files have we seen already?
try:
encoded_files = open(ENCODED_DB).read().splitlines()
except IOError: # create the database of seen files if it doesn't exist
f = open(ENCODED_DB, 'w')
f.write('')
f.close()
encoded_files = []
# Get a list of all available, un-encoded videos
ftp = FTP(FTP_HOST, FTP_USER, FTP_PASS)
ftp.cwd(FTP_DIR)
video_files = [v for v in ftp.nlst() if v not in encoded_files]
# Process the videos
zen = Zencoder(ZENCODER_API_KEY)
for file in video_files:
if file.endswith('mp4'):
print 'processing %s...' % file
filename_stub = file.replace('.mp4', '')
base_url = ZENCODER_DESTINATION_URL + filename_stub + '/'
outputs = make_outputs(base_url)
job = zen.job.create(FTP_SOURCE_URL + file, outputs=outputs)
# mark this video as processed
fo = open(ENCODED_DB, 'a+')
fo.write('%s\n' % file)
fo.close()
else:
print '%s is not a video file, ignoring' % file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment