Skip to content

Commit

Permalink
added subtitles for streamming
Browse files Browse the repository at this point in the history
  • Loading branch information
heniotierra committed Dec 15, 2018
1 parent c096b62 commit ef46825
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 12 deletions.
5 changes: 4 additions & 1 deletion options.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def __init__(self):
self.debug = False # print debug information to terminal
self.generate_track_info = False # generate track information from omxplayer output
self.lang = ""
self.subtitles_lang = ""

# create an options file if necessary
confdir = os.path.expanduser("~") + '/.tboplayer'
Expand Down Expand Up @@ -69,6 +70,7 @@ def read(self,filename):
self.find_lyrics = int(config.get('config','find_lyrics',0))
self.autolyrics_coords = config.get('config','autolyrics_coords',0)
self.lang = config.get('config','lang',0)
self.subtitles_lang = config.get('config','subtitles_lang',0)
self.ytdl_update = int(config.get('config','ytdl_update',0))

if config.get('config','debug',0) == 'on':
Expand Down Expand Up @@ -111,6 +113,7 @@ def create(self,filename):
config.set('config','find_lyrics','0')
config.set('config','autolyrics_coords','+350+350')
config.set('config','lang','en')
config.set('config','subtitles_lang','en')
config.set('config','ytdl_update','1')
with open(filename, 'wb') as configfile:
config.write(configfile)
Expand Down Expand Up @@ -142,8 +145,8 @@ def save_state(self):
config.set('config','find_lyrics',self.find_lyrics)
config.set('config','autolyrics_coords',self.autolyrics_coords)
config.set('config','lang',self.lang)
config.set('config','subtitles_lang',self.subtitles_lang)
config.set('config','ytdl_update',self.ytdl_update)

with open(self.options_file, 'wb') as configfile:
config.write(configfile)
configfile.close()
Expand Down
39 changes: 32 additions & 7 deletions tboplayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,13 @@ def go_ytdl(self, url, playlist=False):
if self.ytdl_state==self._YTDL_STARTING:
self.ytdl_state_machine()

def go_ytdl_subtitles(self, track):
self.ytdl.download_subtitles(self.options.subtitles_lang, track[2])
while (not self.ytdl.subtitle_ready_signal and
not self.ytdl.download_subtitle_failed_signal):
sleep(0.2)
self.start_omx(track[0], skip_ytdl_check = True)


def ytdl_state_machine(self):
if self.ytdl_state == self._YTDL_CLOSED:
Expand Down Expand Up @@ -542,7 +549,7 @@ def treat_video_data(self, url, data):
if tracks:
for track in tracks:
if track[1][0] == url:
self.playlist.replace(track[0],[media_url, data['title'],track[1][PlayList.LOCATION_BACKUP]])
self.playlist.replace(track[0],[media_url, data['title'], url])
if self.play_state == self._OMX_STARTING:
self.start_omx(media_url,skip_ytdl_check=True)
self.refresh_playlist_display()
Expand All @@ -556,7 +563,7 @@ def treat_youtube_playlist_data(self, data):
media_url = self._treat_video_data(entry, data['extractor'], "medium")
if not media_url:
media_url = entry['url']
self.playlist.append([media_url,entry['title'],'',''])
self.playlist.append([media_url,entry['title'],''])
self.playlist.select(self.playlist.length() - len(data['entries']))
self.refresh_playlist_display()
self.root.after(3000, lambda: self.display_selected_track())
Expand Down Expand Up @@ -613,9 +620,19 @@ def start_omx(self, track, skip_ytdl_check=False):
self.playlist.select(index)
self.refresh_playlist_display()
return

if (self.options.omx_subtitles and
not self.ytdl.subtitle_ready_signal and
not self.ytdl.download_subtitle_failed_signal):
track = self.playlist.selected_track()
self.go_ytdl_subtitles(track)
return

track= "'"+ track.replace("'","'\\''") + "'"
opts= (self.options.omx_user_options + " " + self.options.omx_audio_output + " " +
self.options.omx_subtitles + " --vol " + str(self.get_mB()))
" --vol " + str(self.get_mB()) + " " + self.options.omx_subtitles + " " +
" --subtitles " + self.ytdl._YTLAUNCH_SUB_DIR + "/subtitle." + self.options.subtitles_lang + ".srt" if self.ytdl.subtitle_ready_signal else "")

if self.media_is_video():
if not self.options.forbid_windowed_mode and not self.options.full_screen and '--win' not in opts:
mc = self.RE_COORDS.match(self.options.windowed_mode_coords)
Expand All @@ -632,7 +649,7 @@ def start_omx(self, track, skip_ytdl_check=False):

self.monitor('starting omxplayer with args: "%s"' % (opts,))

self.omx = OMXPlayer(track, args=opts, start_playback=True)
self.omx = OMXPlayer(track, args=opts, start_playback=True)

self.monitor(" >Play: " + track + " with " + opts)

Expand Down Expand Up @@ -1850,15 +1867,22 @@ def body(self, master):
self.download_media_url_upon_var.set(_("when adding URL") if config.get('config','download_media_url_upon',0) == "add" else _("when playing URL"))
om_download_media = OptionMenu(master, self.download_media_url_upon_var, _("when adding URL"), _("when playing URL"))
om_download_media.grid(row=21, column=2, sticky=W)


Label(master, text="").grid(row=22, sticky=W)
Label(master, text=_("Interface language:")).grid(row=23, column=0, sticky=W)
self.lang_var=StringVar()
self.lang_var.set(config.get('config','lang',0))
om_lang = OptionMenu(master, self.lang_var, 'en', 'es' , 'fr', 'pt', 'ro', 'ru')
om_lang.grid(row=23, column=2, sticky=W)



Label(master, text="").grid(row=24, sticky=W)
Label(master, text=_("Subtitles language:")).grid(row=25, column=0, sticky=W)
self.subtitles_lang_var=StringVar()
self.subtitles_lang_var.set(config.get('config','subtitles_lang',0))
om_lang = OptionMenu(master, self.subtitles_lang_var, 'ar','de', 'en', 'es' , 'fr', 'ko', 'pt', 'ro', 'ru', 'ch', 'ja')
om_lang.grid(row=25, column=2, sticky=W)


self.forbid_windowed_mode_var = IntVar()
self.forbid_windowed_mode_var.set(int(config.get('config','forbid_windowed_mode',0)))
Expand Down Expand Up @@ -1956,6 +1980,7 @@ def save_options(self):
config.set('config','find_lyrics',self.find_lyrics_var.get())
config.set('config','autolyrics_coords',self.autolyrics_coords_var)
config.set('config','lang',self.lang_var.get())
config.set('config','subtitles_lang',self.lang_var.get())
config.set('config','ytdl_update',self.ytdl_update_var.get())


Expand Down Expand Up @@ -2228,7 +2253,7 @@ def nope(self):
# ***************************************

if __name__ == "__main__":
datestring="30 Out 2018"
datestring="15 Dec 2018"

dbusif_tboplayer = None
try:
Expand Down
128 changes: 128 additions & 0 deletions vtt2srt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/python
#---------------------------------------
# vtt-to-srt.py
# (c) Jansen A. Simanullang
# 02.04.2016 13:39
# LAST CHANGE:
# 02.04.2016 16:56
# recursively visit subdirectories
#---------------------------------------
# usage: python vtt-to-srt.py
#
# example:
# python vtt-to-srt.py
#
# features:
# check a directory and all its subdirectories
# convert all vtt files to srt subtitle format
#
# real world needs:
# converting Coursera's vtt subtitle
# modified by Henio Tierra to provide funcionality to tboplayer

import os, re, sys, io
from stat import *


def convertContent(fileContents):

replacement = re.sub(r'([\d]+)\.([\d]+)', r'\1,\2', fileContents)
replacement = re.sub(r'WEBVTT\n\n', '', replacement)
replacement = re.sub(r'^\d+\n', '', replacement)
replacement = re.sub(r'\n\d+\n', '\n', replacement)

return replacement



def fileCreate(strNamaFile, strData):
#--------------------------------
# fileCreate(strNamaFile, strData)
# create a text file
#
try:

f = open(strNamaFile, "w")
f.writelines(str(strData))
f.close()

except IOError:

strNamaFile = strNamaFile.split(os.sep)[-1]
f = open(strNamaFile, "w")
f.writelines(str(strData))
f.close()

print "file created: " + strNamaFile + "\n"



def readTextFile(strNamaFile):

f = open(strNamaFile, mode='r')

print "file being read: " + strNamaFile + "\n"

return f.read().decode("utf8").encode('ascii', 'ignore')



def vtt_to_srt(strNamaFile):

fileContents = readTextFile(strNamaFile)

strData = ""

strData = strData + convertContent(fileContents)

strNamaFile = strNamaFile.replace(".vtt",".srt")

print strNamaFile

fileCreate(strNamaFile, strData)



def walktree(TopMostPath, callback):

'''recursively descend the directory tree rooted at TopMostPath,
calling the callback function for each regular file'''

for f in os.listdir(TopMostPath):

pathname = os.path.join(TopMostPath, f)
mode = os.stat(pathname)[ST_MODE]

if S_ISDIR(mode):

# It's a directory, recurse into it
walktree(pathname, callback)

elif S_ISREG(mode):

# It's a file, call the callback function
callback(pathname)

else:

# Unknown file type, print a message
print 'Skipping %s' % pathname



def convertVTTtoSRT(file):

if '.vtt' in file:

vtt_to_srt(file)

def vtt2srt(directory):

#just edit the path below

TopMostPath = directory

walktree(TopMostPath, convertVTTtoSRT)

if __name__ == '__main__':
vtt2srt(sys.argv[1])
76 changes: 72 additions & 4 deletions ytdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
from threading import Thread
from time import sleep

from vtt2srt import vtt2srt

# ***************************************
# YTDL CLASS
# ***************************************
Expand All @@ -25,13 +27,18 @@ class Ytdl:
_YTLAUNCH_ARGS_FORMAT = ' -j -f %s --youtube-skip-dash-manifest "%s"'
_YTLAUNCH_PLST_CMD = ''
_YTLAUNCH_PLST_ARGS_FORMAT = ' -J -f mp4 --youtube-skip-dash-manifest "%s"'
_YTLAUNCH_SUB_DIR = '/dev/shm/tbopsubs'
_YTLAUNCH_SUBT_ARGS_FORMAT = ' --write-sub --sub-lang %s --skip-download "%s" --output %s/subtitle'
_YTLAUNCH_AUTOSUBT_ARGS_FORMAT = ' --write-auto-sub --sub-lang %s --skip-download "%s" --output %s/subtitle'

_FINISHED_STATUS = "\n"
_WRN_STATUS = ".*WARNING:.*"
_UPDATED_STATUS = ".*Restart youtube-dl to use the new version.*"
_ERR_STATUS = ".*ERROR:.*"
_SUDO_STATUS = ".*\[sudo\].*"

_NO_SUB_STATUS = ".*WARNING: video doesn't have subtitles.*"
_FOUND_SUB_STATUS = ".*\[info\] Writing video subtitles to:.*"

_SERVICES_REGEXPS = ()
_ACCEPTED_LINK_REXP_FORMAT = "(http[s]{0,1}://(?:\w|\.{0,1})+%s\.(?:[a-z]{2,3})(?:\.[a-z]{2,3}){0,1}/)"

Expand All @@ -47,10 +54,20 @@ class Ytdl:
update_failed_signal = False
password_requested_signal = False
has_password_signal = False

downloading_subtitle_signal = False
downloaded_subtitle_signal = False
downloaded_partial_subtitle_signal = False
download_subtitle_failed_signal = False
subtitle_ready_signal = False

_sudo_password = ''

def __init__(self, options, yt_not_found_callback):
os.system("mount > /dev/null")
try:
os.mkdir(self._YTLAUNCH_SUB_DIR)
except:
pass
self.set_options(options)
self.yt_not_found_callback = yt_not_found_callback
self.compile_regexps()
Expand Down Expand Up @@ -144,7 +161,7 @@ def retrieve_youtube_playlist(self, url):
def whether_to_use_youtube_dl(self, url):
to_use = url[:4] == "http" and any(regxp.match(url) for regxp in self._SERVICES_REGEXPS)
if to_use and not os.path.isfile(self._YTLOCATION):
self.yt_not_found_callback();
self.yt_not_found_callback()
return False
return to_use

Expand Down Expand Up @@ -173,6 +190,57 @@ def quit(self):
except:
return

def download_subtitles(self, lang, url):
self.downloaded_subtitle_signal = False
self.download_subtitle_failed_signal = False
self.subtitle_ready_signal = False
self.downloaded_partial_subtitle_signal = False

if not os.path.isfile(self._YTLOCATION):
self.download_subtitle_failed_signal = True
return
ytcmd = self._YTLOCATION + ((self._YTLAUNCH_SUBT_ARGS_FORMAT) % (lang, url, self._YTLAUNCH_SUB_DIR))
self._subtitled_process = pexpect.spawn(ytcmd)
self.downloading_subtitle_signal = True
Thread(target=self._download_subtitles,args=[lang, url]).start()

def _download_subtitles(self, lang, url, trying = 1):
while self.downloading_subtitle_signal:
try:
index = self._subtitled_process.expect([self._FOUND_SUB_STATUS,
pexpect.EOF,
self._NO_SUB_STATUS,
pexpect.TIMEOUT])
if index == 0:
self.downloaded_partial_subtitle_signal = True
elif index == 1:
if self.downloaded_partial_subtitle_signal:
self.downloaded_subtitle_signal = True
else:
self.download_subtitle_failed_signal = True
self.downloading_subtitle_signal = False
break
elif index in (2,3):
self.downloading_subtitle_signal = False
if trying == 2:
self.download_subtitle_failed_signal = True
break
sleep(0.2)
except Exception, e:
print e
self.download_subtitle_failed_signal = True
self.downloading_subtitle_signal = False
return
if trying == 1 and not self.downloaded_subtitle_signal:
self.downloading_subtitle_signal = True
ytcmd = self._YTLOCATION + ((self._YTLAUNCH_AUTOSUBT_ARGS_FORMAT) % (lang, url, self._YTLAUNCH_SUB_DIR))
self._subtitled_process = pexpect.spawn(ytcmd)
self._download_subtitles(lang, url, trying = 2)
if self.downloaded_subtitle_signal:
vtt2srt(self._YTLAUNCH_SUB_DIR)
os.remove(self._YTLAUNCH_SUB_DIR + "/subtitle." + lang + ".vtt")
self.subtitle_ready_signal = True

def check_for_update(self):
if not os.path.isfile(self._YTLOCATION):
return
Expand Down Expand Up @@ -225,7 +293,7 @@ def _check_for_update(self):
except Exception, e:
print e
break
sleep(5)
sleep(0.5)
if self.updated_signal:
self.compile_regexps(updated=True)
self.updating_signal = False
Expand Down

0 comments on commit ef46825

Please sign in to comment.