| @@ -14,6 +14,17 @@ import concurrent.futures | |||||
| import ntpath | import ntpath | ||||
| import yaml | import yaml | ||||
| from pathlib import Path | from pathlib import Path | ||||
| import logging | |||||
| from systemd.journal import JournalHandler | |||||
| log = logging.getLogger('demotape') | |||||
| log.addHandler(JournalHandler()) | |||||
| log.setLevel(logging.INFO) | |||||
| config_path = Path(__file__).parent / './config.yaml' | config_path = Path(__file__).parent / './config.yaml' | ||||
| with config_path.open() as file: | with config_path.open() as file: | ||||
| @@ -22,13 +33,13 @@ with config_path.open() as file: | |||||
| try: | try: | ||||
| if sys.argv[1] and os.path.exists(sys.argv[1]): | if sys.argv[1] and os.path.exists(sys.argv[1]): | ||||
| ROOT_PATH = sys.argv[1] | ROOT_PATH = sys.argv[1] | ||||
| print('Root path for downloaded streams: ' + ROOT_PATH) | |||||
| log('Root path for downloaded streams: ' + ROOT_PATH) | |||||
| else: | else: | ||||
| print('destination path does not exist') | |||||
| log('destination path does not exist') | |||||
| sys.exit() | sys.exit() | ||||
| except IndexError: | except IndexError: | ||||
| print('Script needs a valid destination path for recorded videos as argument') | |||||
| print('For example: \ndemotape.py /path/to/videos') | |||||
| log('Script needs a valid destination path for recorded videos as argument') | |||||
| log('For example: \ndemotape.py /path/to/videos') | |||||
| sys.exit() | sys.exit() | ||||
| @@ -50,9 +61,9 @@ def generate_channellist(): | |||||
| 'url': 'https://stream.wien.gv.at/live/ngrp:bv' + district_str_lz + '.stream_all/playlist.m3u8' | 'url': 'https://stream.wien.gv.at/live/ngrp:bv' + district_str_lz + '.stream_all/playlist.m3u8' | ||||
| } | } | ||||
| channels.append(channel) | channels.append(channel) | ||||
| print('channels:') | |||||
| log('channels:') | |||||
| for channel in channels: | for channel in channels: | ||||
| print(channel['name'] + ' ' + channel['url']) | |||||
| log(channel['name'] + ' ' + channel['url']) | |||||
| return channels | return channels | ||||
| @@ -66,33 +77,33 @@ def check_stream(url): | |||||
| # no livestream | # no livestream | ||||
| return False | return False | ||||
| except (ValueError, KeyError): | except (ValueError, KeyError): | ||||
| print('some connection error or so') | |||||
| log('some connection error or so') | |||||
| class MyLogger(object): | class MyLogger(object): | ||||
| def debug(self, msg): | def debug(self, msg): | ||||
| #pass | #pass | ||||
| print(msg) | |||||
| log(msg) | |||||
| def warning(self, msg): | def warning(self, msg): | ||||
| #pass | #pass | ||||
| print(msg) | |||||
| log(msg) | |||||
| def error(self, msg): | def error(self, msg): | ||||
| print(msg) | |||||
| log(msg) | |||||
| def my_ytdl_hook(d): | def my_ytdl_hook(d): | ||||
| if d['status'] == 'finished': | if d['status'] == 'finished': | ||||
| print(timestamp() + 'Done downloading!') | |||||
| log(timestamp() + 'Done downloading!') | |||||
| else: | else: | ||||
| print(timestamp() + 'sth went wrong' + d['status']) | |||||
| print(d) | |||||
| log(timestamp() + 'sth went wrong' + d['status']) | |||||
| log(d) | |||||
| def download_stream(channel, dest_path): | def download_stream(channel, dest_path): | ||||
| print('download_stream') | |||||
| log('download_stream') | |||||
| ytdl_opts = { | ytdl_opts = { | ||||
| 'logger': MyLogger(), | 'logger': MyLogger(), | ||||
| 'outtmpl': dest_path, | 'outtmpl': dest_path, | ||||
| @@ -111,42 +122,42 @@ def download_stream(channel, dest_path): | |||||
| ytdl = youtube_dl.YoutubeDL(ytdl_opts) | ytdl = youtube_dl.YoutubeDL(ytdl_opts) | ||||
| try: | try: | ||||
| print(timestamp() + " Downloading: " + channel['url']) | |||||
| log(timestamp() + " Downloading: " + channel['url']) | |||||
| ytdl.download([channel['url']]) | ytdl.download([channel['url']]) | ||||
| except (youtube_dl.utils.DownloadError) as e: | except (youtube_dl.utils.DownloadError) as e: | ||||
| print(timestamp() + " Download error: " + str(e)) | |||||
| log(timestamp() + " Download error: " + str(e)) | |||||
| except (youtube_dl.utils.SameFileError) as e: | except (youtube_dl.utils.SameFileError) as e: | ||||
| print("Download error: " + str(e)) | |||||
| log("Download error: " + str(e)) | |||||
| except (UnicodeDecodeError) as e: | except (UnicodeDecodeError) as e: | ||||
| print("UnicodeDecodeError: " + str(e)) | |||||
| log("UnicodeDecodeError: " + str(e)) | |||||
| def process_channel(channel): | def process_channel(channel): | ||||
| #print('entered function process_channel with ' + channel['name']) | |||||
| #log('entered function process_channel with ' + channel['name']) | |||||
| while True: | while True: | ||||
| print(timestamp() + ' checking ' + channel['name']) | |||||
| log(timestamp() + ' checking ' + channel['name']) | |||||
| if check_stream(channel['url']): | if check_stream(channel['url']): | ||||
| print(channel['name'] + ': stream online! Downloading ...') | |||||
| log(channel['name'] + ': stream online! Downloading ...') | |||||
| dest_dir = ROOT_PATH + '/' + channel['name'] +'/' | dest_dir = ROOT_PATH + '/' + channel['name'] +'/' | ||||
| # create directory if it doesn't exist | # create directory if it doesn't exist | ||||
| if not os.path.exists(dest_dir): | if not os.path.exists(dest_dir): | ||||
| print('creating directory ' + dest_dir) | |||||
| log('creating directory ' + dest_dir) | |||||
| os.makedirs(dest_dir) | os.makedirs(dest_dir) | ||||
| dest_path = get_destpath(channel) # dirctory + filename | dest_path = get_destpath(channel) # dirctory + filename | ||||
| download_stream(channel, dest_path) # also converts video | download_stream(channel, dest_path) # also converts video | ||||
| print(timestamp() + " Uploading video " + dest_path) | |||||
| log(timestamp() + " Uploading video " + dest_path) | |||||
| upload_video(dest_path) | upload_video(dest_path) | ||||
| else: | else: | ||||
| waitingtime = random.randint(50,60) | waitingtime = random.randint(50,60) | ||||
| time.sleep(waitingtime) | time.sleep(waitingtime) | ||||
| print('end processing ' + channel['name'] + ' ... (shouldn\'t happen!)') | |||||
| log('end processing ' + channel['name'] + ' ... (shouldn\'t happen!)') | |||||
| def upload_video(videofile_path): | def upload_video(videofile_path): | ||||
| print('uploading %s' % (videofile_path)) | |||||
| log('uploading %s' % (videofile_path)) | |||||
| credentials = config['webdav']['username'] + ':' + config['webdav']['password'] | credentials = config['webdav']['username'] + ':' + config['webdav']['password'] | ||||
| webdav_baseurl = config['webdav']['base_url'] | webdav_baseurl = config['webdav']['base_url'] | ||||
| filename = ntpath.basename(videofile_path) | filename = ntpath.basename(videofile_path) | ||||
| @@ -158,7 +169,7 @@ def upload_video(videofile_path): | |||||
| delete_video(videofile_path) | delete_video(videofile_path) | ||||
| return true | return true | ||||
| except: | except: | ||||
| print('Error while uploading %s to %s' % (file, webdav_url)) | |||||
| log('Error while uploading %s to %s' % (file, webdav_url)) | |||||
| def delete_video(file): | def delete_video(file): | ||||
| @@ -166,7 +177,7 @@ def delete_video(file): | |||||
| os.system('rm -rf "%s"' % (file)) | os.system('rm -rf "%s"' % (file)) | ||||
| return true | return true | ||||
| except: | except: | ||||
| print('Error while deleting %s' % (file)) | |||||
| log('Error while deleting %s' % (file)) | |||||
| def get_destpath(channel): | def get_destpath(channel): | ||||
| @@ -187,12 +198,12 @@ def main(): | |||||
| try: | try: | ||||
| data = future.result() | data = future.result() | ||||
| except Exception as exc: | except Exception as exc: | ||||
| print('%r generated an exception: %s' % (channel, exc)) | |||||
| log('%r generated an exception: %s' % (channel, exc)) | |||||
| else: | else: | ||||
| print('%r page is %d bytes' % (channel, len(data))) | |||||
| log('%r page is %d bytes' % (channel, len(data))) | |||||
| print('end main (this shouldn\'t happen!)') | |||||
| log('end main (this shouldn\'t happen!)') | |||||
| main() | main() | ||||