2016-06-20 18:33:42 +02:00
|
|
|
from json import dumps
|
|
|
|
from random import sample
|
2016-03-22 22:36:39 +01:00
|
|
|
import os
|
2017-01-15 12:29:40 +01:00
|
|
|
import platform
|
2018-03-03 16:11:23 +01:00
|
|
|
import re
|
2017-02-15 23:15:50 +01:00
|
|
|
from requests import post, codes, Timeout
|
2016-03-22 22:36:39 +01:00
|
|
|
|
|
|
|
from svtplay_dl.log import log
|
2018-03-03 16:11:23 +01:00
|
|
|
from svtplay_dl.utils import which, is_py3, run_program
|
2016-03-22 22:36:39 +01:00
|
|
|
|
|
|
|
|
|
|
|
class postprocess(object):
|
2018-01-30 20:11:37 +01:00
|
|
|
def __init__(self, stream, options, subfixes=[]):
|
2016-03-22 22:36:39 +01:00
|
|
|
self.stream = stream
|
2016-06-20 18:33:42 +02:00
|
|
|
self.merge_subtitle = options.merge_subtitle
|
|
|
|
self.external_subtitle = options.subtitle
|
|
|
|
self.get_all_subtitles = options.get_all_subtitles
|
|
|
|
self.subfixes = subfixes
|
2016-03-30 18:18:43 +02:00
|
|
|
self.detect = None
|
2016-03-22 23:00:50 +01:00
|
|
|
for i in ["ffmpeg", "avconv"]:
|
|
|
|
self.detect = which(i)
|
|
|
|
if self.detect:
|
|
|
|
break
|
|
|
|
|
2016-06-20 18:33:42 +02:00
|
|
|
def sublanguage(self):
|
|
|
|
# parse() function partly borrowed from a guy on github. /thanks!
|
|
|
|
# https://github.com/riobard/srt.py/blob/master/srt.py
|
|
|
|
def parse(self):
|
|
|
|
def parse_block(block):
|
2017-02-15 23:15:50 +01:00
|
|
|
lines = block.strip('-').split('\n')
|
|
|
|
txt = '\r\n'.join(lines[2:])
|
2016-06-20 18:33:42 +02:00
|
|
|
return txt
|
2017-01-15 12:29:40 +01:00
|
|
|
|
|
|
|
if platform.system() == "Windows" and is_py3:
|
|
|
|
fd = open(self, encoding="utf8")
|
|
|
|
else:
|
|
|
|
fd = open(self)
|
2016-09-07 17:31:14 +02:00
|
|
|
return list(map(parse_block,
|
2017-02-15 23:15:50 +01:00
|
|
|
fd.read().strip().replace('\r', '').split('\n\n')))
|
|
|
|
|
2016-06-20 18:33:42 +02:00
|
|
|
def query(self):
|
2017-02-15 23:15:50 +01:00
|
|
|
random_sentences = ' '.join(sample(parse(self), 8)).replace('\r\n', '')
|
2016-06-20 18:33:42 +02:00
|
|
|
url = 'https://whatlanguage.herokuapp.com'
|
2017-02-15 23:15:50 +01:00
|
|
|
payload = {"query": random_sentences}
|
2018-01-30 20:11:37 +01:00
|
|
|
# Note: requests handles json from version 2.4.2 and onwards so i use json.dumps for now.
|
|
|
|
headers = {'content-type': 'application/json'}
|
2016-06-20 18:33:42 +02:00
|
|
|
try:
|
2018-01-30 20:11:37 +01:00
|
|
|
# Note: reasonable timeout i guess? svtplay-dl is mainly used while multitasking i presume,
|
|
|
|
# and it is heroku after all (fast enough)
|
|
|
|
r = post(url, data=dumps(payload), headers=headers, timeout=30)
|
2016-06-20 18:33:42 +02:00
|
|
|
if r.status_code == codes.ok:
|
2016-11-27 19:20:41 +01:00
|
|
|
try:
|
|
|
|
response = r.json()
|
|
|
|
return response['language']
|
|
|
|
except TypeError:
|
|
|
|
return 'und'
|
2016-06-20 18:33:42 +02:00
|
|
|
else:
|
|
|
|
log.error("Server error appeared. Setting language as undetermined.")
|
|
|
|
return 'und'
|
|
|
|
except Timeout:
|
|
|
|
log.error("30 seconds server timeout reached. Setting language as undetermined.")
|
|
|
|
return 'und'
|
|
|
|
|
|
|
|
langs = []
|
|
|
|
exceptions = {
|
|
|
|
'lulesamiska': 'smj',
|
|
|
|
'meankieli': 'fit',
|
|
|
|
'jiddisch': 'yid'
|
|
|
|
}
|
|
|
|
if len(self.subfixes) >= 2:
|
|
|
|
log.info("Determining the languages of the subtitles.")
|
2018-01-30 20:11:37 +01:00
|
|
|
else:
|
|
|
|
log.info("Determining the language of the subtitle.")
|
2016-06-20 18:33:42 +02:00
|
|
|
if self.get_all_subtitles:
|
|
|
|
from re import match
|
|
|
|
for subfix in self.subfixes:
|
|
|
|
if [exceptions[key] for key in exceptions.keys() if match(key, subfix.strip('-'))]:
|
|
|
|
if 'oversattning' in subfix.strip('-'):
|
|
|
|
subfix = subfix.strip('-').split('.')[0]
|
|
|
|
else:
|
|
|
|
subfix = subfix.strip('-')
|
|
|
|
langs += [exceptions[subfix]]
|
|
|
|
continue
|
2017-02-12 09:01:40 +01:00
|
|
|
subfile = "{0}.srt".format(os.path.splitext(self.stream.options.output)[0] + subfix)
|
2016-06-20 18:33:42 +02:00
|
|
|
langs += [query(subfile)]
|
|
|
|
else:
|
2017-02-12 09:01:40 +01:00
|
|
|
subfile = "{0}.srt".format(os.path.splitext(self.stream.options.output)[0])
|
2016-06-20 18:33:42 +02:00
|
|
|
langs += [query(subfile)]
|
|
|
|
if len(langs) >= 2:
|
|
|
|
log.info("Language codes: " + ', '.join(langs))
|
2018-01-30 20:11:37 +01:00
|
|
|
else:
|
|
|
|
log.info("Language code: " + langs[0])
|
2016-06-20 18:33:42 +02:00
|
|
|
return langs
|
|
|
|
|
2016-03-26 21:38:31 +01:00
|
|
|
def remux(self):
|
2016-03-30 18:18:43 +02:00
|
|
|
if self.detect is None:
|
2016-06-02 01:47:25 +02:00
|
|
|
log.error("Cant detect ffmpeg or avconv. Cant mux files without it.")
|
2016-03-22 22:36:39 +01:00
|
|
|
return
|
|
|
|
if self.stream.finished is False:
|
|
|
|
return
|
2016-06-20 18:33:42 +02:00
|
|
|
|
2016-06-02 01:47:25 +02:00
|
|
|
if self.stream.options.output.endswith('.mp4') is False:
|
|
|
|
orig_filename = self.stream.options.output
|
|
|
|
name, ext = os.path.splitext(orig_filename)
|
2017-02-12 09:01:40 +01:00
|
|
|
new_name = u"{0}.mp4".format(name)
|
2016-06-20 18:33:42 +02:00
|
|
|
|
2018-03-03 16:11:23 +01:00
|
|
|
cmd = [self.detect, "-i", orig_filename]
|
|
|
|
_, stdout, stderr = run_program(cmd, False) # return 1 is good here.
|
|
|
|
videotrack, audiotrack = self._checktracks(stderr)
|
|
|
|
|
2016-06-20 18:33:42 +02:00
|
|
|
if self.merge_subtitle:
|
2017-03-14 23:07:06 +01:00
|
|
|
log.info(u"Muxing {0} and merging its subtitle into {1}".format(orig_filename, new_name))
|
2016-06-20 18:33:42 +02:00
|
|
|
else:
|
2017-03-14 23:07:06 +01:00
|
|
|
log.info(u"Muxing {0} into {1}".format(orig_filename, new_name))
|
2017-01-02 21:09:35 +01:00
|
|
|
|
2017-02-12 09:01:40 +01:00
|
|
|
tempfile = u"{0}.temp".format(orig_filename)
|
2018-03-03 16:11:23 +01:00
|
|
|
arguments = ["-map", "0:{}".format(videotrack), "-map", "0:{}".format(audiotrack), "-c", "copy", "-copyts", "-f", "mp4"]
|
2016-06-02 01:47:25 +02:00
|
|
|
if ext == ".ts":
|
|
|
|
arguments += ["-bsf:a", "aac_adtstoasc"]
|
2017-02-15 23:15:50 +01:00
|
|
|
|
2016-06-20 18:33:42 +02:00
|
|
|
if self.merge_subtitle:
|
|
|
|
langs = self.sublanguage()
|
|
|
|
for stream_num, language in enumerate(langs):
|
2018-01-30 20:11:37 +01:00
|
|
|
arguments += ["-map", str(stream_num + 1), "-c:s:" + str(stream_num), "mov_text",
|
|
|
|
"-metadata:s:s:" + str(stream_num), "language=" + language]
|
2016-06-20 18:33:42 +02:00
|
|
|
if len(self.subfixes) >= 2:
|
|
|
|
for subfix in self.subfixes:
|
2017-02-12 09:01:40 +01:00
|
|
|
subfile = "{0}.srt".format(name + subfix)
|
2016-06-20 18:33:42 +02:00
|
|
|
cmd += ["-i", subfile]
|
|
|
|
else:
|
2017-02-12 09:01:40 +01:00
|
|
|
subfile = "{0}.srt".format(name)
|
2016-06-20 18:33:42 +02:00
|
|
|
cmd += ["-i", subfile]
|
2017-02-15 23:15:50 +01:00
|
|
|
|
2016-06-20 18:33:42 +02:00
|
|
|
arguments += ["-y", tempfile]
|
2016-06-02 01:47:25 +02:00
|
|
|
cmd += arguments
|
2018-03-03 16:11:23 +01:00
|
|
|
returncode, stdout, stderr = run_program(cmd)
|
|
|
|
if returncode != 0:
|
2016-06-02 01:47:25 +02:00
|
|
|
return
|
2017-02-15 23:15:50 +01:00
|
|
|
|
2016-06-20 18:33:42 +02:00
|
|
|
if self.merge_subtitle and not self.external_subtitle:
|
|
|
|
log.info("Muxing done, removing the old files.")
|
|
|
|
if len(self.subfixes) >= 2:
|
|
|
|
for subfix in self.subfixes:
|
2017-02-12 09:01:40 +01:00
|
|
|
subfile = "{0}.srt".format(name + subfix)
|
2016-06-20 18:33:42 +02:00
|
|
|
os.remove(subfile)
|
2018-01-30 20:11:37 +01:00
|
|
|
else:
|
|
|
|
os.remove(subfile)
|
|
|
|
else:
|
|
|
|
log.info("Muxing done, removing the old file.")
|
2016-06-20 18:33:42 +02:00
|
|
|
os.remove(orig_filename)
|
2016-06-02 01:47:25 +02:00
|
|
|
os.rename(tempfile, new_name)
|
2016-03-22 22:36:39 +01:00
|
|
|
|
2016-03-26 21:38:31 +01:00
|
|
|
def merge(self):
|
2016-03-30 18:18:43 +02:00
|
|
|
if self.detect is None:
|
2016-06-02 01:47:25 +02:00
|
|
|
log.error("Cant detect ffmpeg or avconv. Cant mux files without it.")
|
2016-03-26 21:38:31 +01:00
|
|
|
return
|
|
|
|
if self.stream.finished is False:
|
|
|
|
return
|
2016-06-20 18:33:42 +02:00
|
|
|
|
2016-03-26 21:38:31 +01:00
|
|
|
orig_filename = self.stream.options.output
|
2018-03-03 16:11:23 +01:00
|
|
|
|
|
|
|
cmd = [self.detect, "-i", orig_filename]
|
|
|
|
_, stdout, stderr = run_program(cmd, False) # return 1 is good here.
|
|
|
|
videotrack, audiotrack = self._checktracks(stderr)
|
|
|
|
|
2016-06-20 18:33:42 +02:00
|
|
|
if self.merge_subtitle:
|
2017-03-14 23:07:06 +01:00
|
|
|
log.info("Merge audio, video and subtitle into {0}".format(orig_filename))
|
2016-06-20 18:33:42 +02:00
|
|
|
else:
|
2017-03-14 23:07:06 +01:00
|
|
|
log.info("Merge audio and video into {0}".format(orig_filename))
|
2017-01-02 21:09:35 +01:00
|
|
|
|
2017-02-12 09:01:40 +01:00
|
|
|
tempfile = u"{0}.temp".format(orig_filename)
|
2018-03-06 21:48:37 +01:00
|
|
|
name, ext = os.path.splitext(orig_filename)
|
2016-06-20 18:33:42 +02:00
|
|
|
arguments = ["-c:v", "copy", "-c:a", "copy", "-f", "mp4"]
|
2018-03-06 21:48:37 +01:00
|
|
|
if ext == ".ts":
|
|
|
|
audio_filename = u"{0}.audio.ts".format(name)
|
|
|
|
arguments += ["-bsf:a", "aac_adtstoasc"]
|
|
|
|
else:
|
|
|
|
audio_filename = u"{0}.m4a".format(name)
|
2016-03-26 21:38:31 +01:00
|
|
|
cmd = [self.detect, "-i", orig_filename, "-i", audio_filename]
|
2016-06-20 18:33:42 +02:00
|
|
|
|
|
|
|
if self.merge_subtitle:
|
|
|
|
langs = self.sublanguage()
|
2018-03-03 16:11:23 +01:00
|
|
|
for stream_num, language in enumerate(langs, start=audiotrack + 1):
|
|
|
|
arguments += ["-map", "{}".format(videotrack), "-map", "{}".format(audiotrack), "-map", str(stream_num), "-c:s:" + str(stream_num - 2), "mov_text",
|
2018-01-30 20:11:37 +01:00
|
|
|
"-metadata:s:s:" + str(stream_num - 2), "language=" + language]
|
2016-06-20 18:33:42 +02:00
|
|
|
if len(self.subfixes) >= 2:
|
|
|
|
for subfix in self.subfixes:
|
2017-02-12 09:01:40 +01:00
|
|
|
subfile = "{0}.srt".format(name + subfix)
|
2016-06-20 18:33:42 +02:00
|
|
|
cmd += ["-i", subfile]
|
|
|
|
else:
|
2017-02-12 09:01:40 +01:00
|
|
|
subfile = "{0}.srt".format(name)
|
2016-06-20 18:33:42 +02:00
|
|
|
cmd += ["-i", subfile]
|
2017-02-15 23:15:50 +01:00
|
|
|
|
2016-06-20 18:33:42 +02:00
|
|
|
arguments += ["-y", tempfile]
|
2016-03-26 21:38:31 +01:00
|
|
|
cmd += arguments
|
2018-03-03 16:11:23 +01:00
|
|
|
returncode, stdout, stderr = run_program(cmd)
|
2018-03-09 22:19:27 +01:00
|
|
|
if returncode != 0:
|
2016-03-26 21:38:31 +01:00
|
|
|
return
|
2016-07-01 00:30:55 +02:00
|
|
|
|
2016-03-26 21:38:31 +01:00
|
|
|
log.info("Merging done, removing old files.")
|
2016-06-20 18:33:42 +02:00
|
|
|
os.remove(orig_filename)
|
2016-03-26 21:38:31 +01:00
|
|
|
os.remove(audio_filename)
|
2016-06-20 18:33:42 +02:00
|
|
|
if self.merge_subtitle and not self.external_subtitle:
|
|
|
|
if len(self.subfixes) >= 2:
|
|
|
|
for subfix in self.subfixes:
|
2017-02-12 09:01:40 +01:00
|
|
|
subfile = "{0}.srt".format(name + subfix)
|
2016-06-20 18:33:42 +02:00
|
|
|
os.remove(subfile)
|
2018-01-30 20:11:37 +01:00
|
|
|
else:
|
|
|
|
os.remove(subfile)
|
2016-07-01 00:30:55 +02:00
|
|
|
os.rename(tempfile, orig_filename)
|
2018-03-03 16:11:23 +01:00
|
|
|
|
|
|
|
def _checktracks(self, output):
|
|
|
|
allstuff = re.findall("Stream \#\d:(\d)\[[^\[]+\]: (Video|Audio): (.*)", output)
|
|
|
|
videotrack = 0
|
|
|
|
audiotrack = 1
|
|
|
|
for stream in allstuff:
|
|
|
|
if stream[1] == "Video":
|
|
|
|
videotrack = stream[0]
|
|
|
|
if stream[1] == "Audio":
|
|
|
|
if stream[2] == "mp3, 0 channels":
|
|
|
|
continue
|
|
|
|
audiotrack = stream[0]
|
|
|
|
|
|
|
|
return videotrack, audiotrack
|