Skip to content
25 changes: 25 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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)'



31 changes: 25 additions & 6 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions podimo/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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", ""))
7 changes: 7 additions & 0 deletions podimo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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