63 lines
1.7 KiB
Python
63 lines
1.7 KiB
Python
#
|
|
# Downloads the video/audio as a stream from a provided link using youtube-dl
|
|
# does not save the file, only the most recent fragment is held. Thus, this is
|
|
# ideal for devices with little memory
|
|
# TODO gather video metadata before download
|
|
#
|
|
|
|
import tempfile
|
|
import sys
|
|
import subprocess
|
|
import os
|
|
import pip
|
|
import signal
|
|
from logger import logger
|
|
|
|
def updateYoutubeDL():
|
|
pip.main(['install', '--target=' + dirpath, '--upgrade', 'youtube_dl'])
|
|
|
|
def importYoutubeDL():
|
|
return __import__('youtube_dl')
|
|
|
|
dirpath = tempfile.mkdtemp()
|
|
sys.path.append(dirpath)
|
|
updateYoutubeDL()
|
|
|
|
def executeYoutubeDL(url, cb):
|
|
env = dict(os.environ)
|
|
env["PYTHONPATH"] = dirpath
|
|
cmd = [
|
|
sys.executable,
|
|
dirpath + "/bin/youtube-dl",
|
|
"-o", "-",
|
|
"-f", "bestaudio/best",
|
|
# "--audio-format", "mp3", "-x", # cannot do because it requires a tmp file to re-encode
|
|
"--prefer-ffmpeg",
|
|
"--no-mark-watched",
|
|
"--geo-bypass",
|
|
"--no-playlist",
|
|
"--retries", "100",
|
|
"--no-call-home",
|
|
url
|
|
]
|
|
popen = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid)
|
|
|
|
# monitor the stdout and send to callback, if result from callback function is true,
|
|
# then kill the download process
|
|
BUFFER_SIZE = 8096
|
|
logger.add(popen.stderr, "youtube-dl.log")
|
|
for chunk in iter(lambda: popen.stdout.read(BUFFER_SIZE), b''):
|
|
if cb(chunk):
|
|
os.killpg(os.getpgid(popen.pid), signal.SIGTERM)
|
|
break
|
|
popen.stdout.close()
|
|
popen.wait()
|
|
|
|
def download(url, cb):
|
|
# update youtube-dl
|
|
# TODO: do this only every once in a while
|
|
# updateYoutubeDL()
|
|
|
|
# start downloader so that it's stdout (with fragments) may be captured
|
|
executeYoutubeDL(url, cb)
|