diff --git a/.env.example b/.env.example index 80444d8..dc191ad 100644 --- a/.env.example +++ b/.env.example @@ -115,3 +115,28 @@ PODIMO_BIND_HOST="127.0.0.1:12104" # Enable extra logging in debugging mode # Set to false if you don't want to see as much information DEBUG=true + +############# +## VIDEO ## +############# +# Experimental: enable rudimentary video support for video podcasts. +# This won't make the video available in your podcast app, but will add a link +# to the video (m3u8 stream) in the podcast description. +# This is a very experimental feature, may not work for all video podcasts. +# Enable this feature by setting the following variable to true. +# ENABLE_VIDEO=false + +# Optionally, you can check if a podcast has a video version by making a +# request to the Podimo servers. This isn't properly tested and might slow +# down the tool or break it. +# Enable this feature by setting the following variable to true. +# ENABLE_VIDEO_CHECK=false + +# Optionally, you can add a custom string to the title of podcasts that have +# a video version (that will be in the description). To do so, set the following +# variable to the string you want to add (e.g. "(video available)"). +# Remember to add a space at the beginning of the string. +# VIDEO_TITLE_SUFFIX='(video available)' + + + diff --git a/main.py b/main.py index d540132..6738956 100644 --- a/main.py +++ b/main.py @@ -32,7 +32,7 @@ from hypercorn.asyncio import serve from urllib.parse import quote from podimo.config import * -from podimo.utils import generateHeaders, randomHexId +from podimo.utils import generateHeaders, randomHexId, video_exists_at_url import podimo.cache as cache import cloudscraper import traceback @@ -299,14 +299,33 @@ def extract_audio_url(episode): async def addFeedEntry(fg, episode, session, locale): fe = fg.add_entry() fe.guid(episode["id"]) - fe.title(episode["title"]) - fe.description(episode["description"]) - fe.pubDate(episode.get("publishDatetime", episode.get("datetime"))) - fe.podcast.itunes_image(episode["imageUrl"]) url, duration = extract_audio_url(episode) if url is None: - return + return + + # Generate the video url and paste it as prefix in the description :') + ep_id = url.split("/")[-1].replace(".mp3", "") + hls_url = f"https://cdn.podimo.com/hls-media/{ep_id}/stream_video_high/stream.m3u8" + + if VIDEO_ENABLED: + if VIDEO_CHECK_ENABLED: + if video_exists_at_url(hls_url): + fe.description( + f"Video URL found at: {hls_url} (experimental) || {episode['description']}" + ) + fe.title(episode["title"] + VIDEO_TITLE_SUFFIX) + else: + fe.description(f"Video URL: {hls_url} (not verified) || {episode['description']}") + fe.title(episode["title"]) + + else: + fe.description(episode["description"]) + fe.title(episode["title"]) + + fe.pubDate(episode.get("publishDatetime", episode.get("datetime"))) + fe.podcast.itunes_image(episode["imageUrl"]) + logging.debug(f"Found podcast '{episode['title']}'") fe.podcast.itunes_duration(duration) content_length, content_type = await urlHeadInfo(session, episode['id'], url, locale) diff --git a/podimo/config.py b/podimo/config.py index b9bb6cb..14ebb23 100644 --- a/podimo/config.py +++ b/podimo/config.py @@ -115,3 +115,13 @@ if line and not line.startswith('#'): line = line.split(' ', 1)[0] BLOCKED.add(line) + + +# load experimental video support env vars +VIDEO_ENABLED = bool( + str(config.get("ENABLE_VIDEO", None)).lower() in ["true", "1", "t", "y", "yes"] +) +VIDEO_CHECK_ENABLED = bool( + str(config.get("ENABLE_VIDEO_CHECK", None)).lower() in ["true", "1", "t", "y", "yes"] +) +VIDEO_TITLE_SUFFIX = str(config.get("VIDEO_TITLE_SUFFIX", "")) diff --git a/podimo/utils.py b/podimo/utils.py index 9d6803b..b38cb43 100644 --- a/podimo/utils.py +++ b/podimo/utils.py @@ -21,6 +21,7 @@ from random import choice, randint from hashlib import sha256 import asyncio +import requests from functools import wraps, partial def randomHexId(length: int): @@ -68,3 +69,9 @@ async def run(*args, loop=None, executor=None, **kwargs): pfunc = partial(func, *args, **kwargs) return await loop.run_in_executor(executor, pfunc) return run + +def video_exists_at_url(url: str) -> bool: + res = requests.get(url) + if res.text.strip().startswith("#EXTM3U"): + return True + return False