Created
February 12, 2012 03:49
-
-
Save darvin/1806112 to your computer and use it in GitHub Desktop.
HTTP Live Stream encoder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__author__ = 'darvin' | |
import os, errno, tempfile, subprocess | |
from os.path import join | |
from optparse import OptionParser | |
def mkdir_p(path): | |
try: | |
os.makedirs(path) | |
except OSError as exc: # Python >2.5 | |
if exc.errno == errno.EEXIST: | |
pass | |
else: raise | |
def flat_list(lst): | |
result = [] | |
for tpl in lst: | |
for item in tpl: | |
result.append(item) | |
return result | |
#basic constants | |
ENCRYPTED = True | |
BITRATES = ( | |
('hi', 320), | |
('mid', 160), | |
('low', 48) | |
) | |
BASE_URL = 'http://10.0.1.5/~darvin' | |
OUTPUT_FORMAT = "aac" | |
#tuning | |
BASE_DATA_URL = lambda track_name, bitrate_name: '{base_url}/data/{track_name}/{bitrate_name}/'.format(base_url=BASE_URL, track_name=track_name, bitrate_name=bitrate_name) | |
BASE_KEY_URL = lambda track_name, bitrate_name: '{base_url}/keys/{track_name}/'.format(base_url=BASE_URL, track_name=track_name, bitrate_name=bitrate_name) | |
BASE_DATA_PATH_WITHOUT_BITRATE = lambda track_name: join('data',track_name) | |
BASE_DATA_PATH = lambda track_name, bitrate_name: join('data',track_name, bitrate_name) | |
BASE_KEY_PATH = lambda track_name, bitrate_name: join('keys',track_name) | |
#commands | |
FFMPEG_COMMAND = lambda input, output, bitrate: \ | |
["/usr/local/bin/ffmpeg", | |
"-i", input, | |
"-b", "{}k".format(bitrate), | |
output] | |
VARIANTPLAYLISTCREATOR_COMMAND = lambda output, paths_list :\ | |
[ | |
"variantplaylistcreator", | |
"-o", output, | |
] + flat_list(paths_list) | |
if ENCRYPTED: | |
MEDIAFILESEGMENTER_COMMAND = lambda input, output, base_data_url, base_key_path, key_url : \ | |
[ | |
"mediafilesegmenter", | |
input, | |
"-generate-variant-plist", | |
"-file-base", output, | |
"-base-url", base_data_url, | |
"-k", base_key_path, | |
"-encrypt-key-url", key_url | |
] | |
else: | |
MEDIAFILESEGMENTER_COMMAND = lambda input, output, base_data_url, base_key_path, key_url :\ | |
[ | |
"mediafilesegmenter", | |
input, | |
"-generate-variant-plist", | |
"-file-base", output, | |
"-base-url", base_data_url, | |
] | |
def process_encoded_file(track_name, filename, bitrate_name, output_dir): | |
result_output_path = join(output_dir, BASE_DATA_PATH(track_name, bitrate_name)) | |
result_key_path = join(output_dir, BASE_KEY_PATH(track_name, bitrate_name)) | |
mkdir_p(result_output_path) | |
if ENCRYPTED: | |
mkdir_p(result_key_path) | |
subprocess.call(MEDIAFILESEGMENTER_COMMAND(input=filename, | |
output=result_output_path, | |
base_data_url=BASE_DATA_URL(track_name, bitrate_name), | |
base_key_path=result_key_path, | |
key_url=BASE_KEY_URL(track_name, bitrate_name))) | |
return BASE_DATA_URL(track_name, bitrate_name)+ "prog_index.m3u8", os.path.splitext( filename)[0]+".plist" | |
def process_input_file(filename, output_dir): | |
track_name = os.path.splitext( os.path.basename(filename))[0] | |
output_paths = [] | |
for bitrate_name, bitrate in BITRATES: | |
tfilename = tempfile.mktemp(suffix=".{}".format(OUTPUT_FORMAT)) | |
subprocess.call(FFMPEG_COMMAND(bitrate=bitrate, input=filename, output=tfilename)) | |
output_paths.append(process_encoded_file(track_name=track_name, filename=tfilename, bitrate_name=bitrate_name, output_dir=output_dir)) | |
subprocess.call( | |
VARIANTPLAYLISTCREATOR_COMMAND( | |
output=join(output_dir, BASE_DATA_PATH_WITHOUT_BITRATE(track_name), "all.m3u8"), | |
paths_list=output_paths)) | |
if __name__=="__main__": | |
parser = OptionParser() | |
parser.add_option("-i", "--input", dest="input", | |
help="input FILE or DIR", metavar="FILE_OR_DIR") | |
parser.add_option("-o", "--output", dest="output", | |
help="output FILE or DIR", metavar="FILE_OR_DIR") | |
(options, args) = parser.parse_args() | |
if os.path.isdir(options.input): | |
for fname in os.listdir(options.input): | |
process_input_file(os.path.abspath(join(options.input, fname)), output_dir=os.path.abspath(options.output)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment