Skip to content

Instantly share code, notes, and snippets.

@pxia
Last active July 8, 2019 11:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pxia/b8d09adc759b8530513c8ea9ad193670 to your computer and use it in GitHub Desktop.
Save pxia/b8d09adc759b8530513c8ea9ad193670 to your computer and use it in GitHub Desktop.
download and merge m3u8
#!/usr/bin/env python3
import time
import m3u8
import sys
import subprocess
from os.path import abspath
from os import makedirs
def getNewDirName():
localtime = time.localtime()
name = time.strftime("%Y%m%d_%H%M%S", localtime)
return name
class M3u8Session:
def __init__(self, url, dir=None):
self.dir = dir if dir else getNewDirName()
try:
makedirs(self.dir)
except:
pass
self.m3u8 = m3u8.load(url)
self.localM3u8Path = abspath(self.dir + "/ffmpeg.m3u8")
self.aria2InputLines = []
def rewriteKeyUrls(self):
for i, key in enumerate(self.m3u8.keys):
if key is None: continue
self.aria2InputLines.append("%s" % key.absolute_uri)
self.aria2InputLines.append("\tout=%d.key" % i)
key.uri = "%d.key" % i
def getSegmentUrls(self):
self.aria2InputLines += list(
map(lambda s: s.absolute_uri, self.m3u8.segments))
def dumpM3u8(self):
self.rewriteKeyUrls()
self.getSegmentUrls()
self.m3u8.dump(self.localM3u8Path)
def aria2AndWait(self):
aria2 = aria2 = subprocess.Popen(
[
'aria2c', '--console-log-level', 'warn', '-d',
abspath(self.dir), '-x', '16', '-j', '16', '-c', '-i', '-'
],
stdin=subprocess.PIPE)
aria2.communicate("\n".join(self.aria2InputLines).encode("utf-8"))
return aria2.returncode == 0
def ffmpegAndWait(self):
ffmpeg = subprocess.Popen([
'ffmpeg', '-allowed_extensions', 'ALL', '-i', self.localM3u8Path,
'-c', 'copy', 'output.mp4'
])
ffmpeg.communicate()
return ffmpeg.returncode == 0
def run(self):
self.dumpM3u8()
assert self.aria2AndWait()
assert self.ffmpegAndWait()
return
def main():
url = sys.argv[1]
directory = sys.argv[2] if len(sys.argv) >= 3 else None
m = M3u8Session(url, directory)
m.run()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment