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 subprocess
import os
2017-01-15 12:29:40 +01:00
import platform
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
2017-01-15 12:29:40 +01:00
from svtplay_dl . utils import which , is_py3
2016-03-22 22:36:39 +01:00
class postprocess ( object ) :
2016-06-20 18:33:42 +02: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 }
2016-06-20 18:33:42 +02:00
headers = { ' content-type ' : ' application/json ' } # Note: requests handles json from version 2.4.2 and onwards so i use json.dumps for now.
try :
r = post ( url , data = dumps ( payload ) , headers = headers , timeout = 30 ) # Note: reasonable timeout i guess? svtplay-dl is mainly used while multitasking i presume, and it is heroku after all (fast enough)
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. " )
else : log . info ( " Determining the language of the subtitle. " )
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 ) )
else : log . info ( " Language code: " + langs [ 0 ] )
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
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 )
2016-06-20 18:33:42 +02:00
arguments = [ " -map " , " 0:v " , " -map " , " 0:a " , " -c " , " copy " , " -copyts " , " -f " , " mp4 " ]
2016-06-02 01:47:25 +02:00
if ext == " .ts " :
arguments + = [ " -bsf:a " , " aac_adtstoasc " ]
cmd = [ self . detect , " -i " , orig_filename ]
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 ) :
arguments + = [ " -map " , str ( stream_num + 1 ) , " -c:s: " + str ( stream_num ) , " mov_text " , " -metadata:s:s: " + str ( stream_num ) , " language= " + language ]
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
p = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE , stdin = subprocess . PIPE )
stdout , stderr = p . communicate ( )
if p . returncode != 0 :
stderr = stderr . decode ( ' utf-8 ' , ' replace ' )
msg = stderr . strip ( ) . split ( ' \n ' ) [ - 1 ]
2017-03-14 23:07:06 +01:00
log . error ( " Something went wrong: {0} " . format ( msg ) )
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 )
else : os . remove ( subfile )
else : log . info ( " Muxing done, removing the old file. " )
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
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 )
2016-06-20 18:33:42 +02:00
name = os . path . splitext ( orig_filename ) [ 0 ]
2017-02-12 09:01:40 +01:00
audio_filename = u " {0} .m4a " . format ( name )
2016-06-20 18:33:42 +02:00
arguments = [ " -c:v " , " copy " , " -c:a " , " copy " , " -f " , " mp4 " ]
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 ( )
2017-02-15 23:15:50 +01:00
for stream_num , language in enumerate ( langs , start = 2 ) :
2016-07-01 00:30:55 +02:00
arguments + = [ " -map " , " 0 " , " -map " , " 1 " , " -map " , str ( stream_num ) , " -c:s: " + str ( stream_num - 2 ) , " mov_text " , " -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
p = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE , stdin = subprocess . PIPE )
stdout , stderr = p . communicate ( )
if p . returncode != 0 :
stderr = stderr . decode ( ' utf-8 ' , ' replace ' )
msg = stderr . strip ( ) . split ( ' \n ' ) [ - 1 ]
2017-03-14 23:07:06 +01:00
log . error ( " Something went wrong: {0} " . format ( msg ) )
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 )
else : os . remove ( subfile )
2016-07-01 00:30:55 +02:00
os . rename ( tempfile , orig_filename )