Skip to content

Commit

Permalink
work work work...
Browse files Browse the repository at this point in the history
- add more ffmpeg config options to .env.example
- we're not using wrp on the servers any more so take that out of
servers.json
- add mutagen for getting the audio duration (needed for discs.json)
- update resource pack builder to use pack version in filenames
- break out some more logic into separate functions
  • Loading branch information
RalphORama committed Oct 19, 2023
1 parent c88d642 commit 86d33b7
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 110 deletions.
17 changes: 13 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@ RSS_URL="https://anchor.fm/s/da4e26b0/podcast/rss"
PTERODACTYL_URL="https://pterodactyl.example.com"
PTERODACTYL_API_KEY=""

# Generated resource packs will be named "{RESOURCE_PACK_NAME}_{PACK_VERSION}.zip"
RESOURCE_PACK_NAME="resourcepack"

# Timeout for HTTP requests, in ms. 1000 = 1 second. If your podcast is hosted
# on a very slow service you might want to bump this value up to 5000 or 10000
HTTP_TIMEOUT=1000

# From the FFMPEG wiki (https://trac.ffmpeg.org/wiki/TheoraVorbisEncodingGuide)
# Range is -1.0 to 10.0, where 10.0 is highest quality.
# The formula 16×(q+4) is used below 4, 32×q is used below 8, and 64×(q-4) otherwise.
# A value of 2 targets 90kbps, the same bitrate as vanilla Minecraft music discs.
# A value of 0 is generally fine for podcasts which are lees complex than music.
# The original 13 discs were encoded with q=0 (~64kbit/s) and a sample rate of 44.1kHz
# Newer music discs were encoded qith q=7 (~224kbit/s) and a sample rate of 48kHz
AUDIO_QUALITY=0
AUDIO_SAMPLERATE=44100

# Normalize loudness. Good for podcasts that don't master their audio and may
# have very loud/very quiet sections
# Set to 1 to enable audio normalization
AUDIO_NORMALIZE=0
1 change: 0 additions & 1 deletion data/servers.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"id": "hijklmnop",
"command_delay": 1,
"commands": [
"wrp reload",
"jext",
"tellraw @a [\"[\",{\"text\":\"RSS\",\"color\":\"light_purple\"},\"] A new episode of Podcast About List was just released!\"]",
"tellraw @a [\"[\",{\"text\":\"RSS\",\"color\":\"light_purple\"},\"] Reconnect to the server and use the command \",{\"text\":\"/paldisc\",\"color\":\"aqua\"},\" to listen on a jukebox!\"]"
Expand Down
159 changes: 83 additions & 76 deletions poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ requests = "^2.31.0"
rss-parser = "^1.1.1"
python-ffmpeg = "^2.0.4"
pypng = "^0.20220715.0"
mutagen = "^1.47.0"

[tool.poetry.group.dev.dependencies]
black = "^23.9.1"
Expand Down
9 changes: 6 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ charset-normalizer==3.3.0 ; python_version >= "3.11" and python_version < "4.0"
idna==3.4 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
mutagen==1.47.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:719fadef0a978c31b4cf3c956261b3c58b6948b32023078a2117b1de09f0fc99 \
--hash=sha256:edd96f50c5907a9539d8e5bba7245f62c9f520aef333d13392a79a4f70aca719
pydantic==1.10.13 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548 \
--hash=sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80 \
Expand Down Expand Up @@ -153,9 +156,9 @@ rss-parser==1.1.1 ; python_version >= "3.11" and python_version < "4.0" \
typing-extensions==4.8.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0 \
--hash=sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef
urllib3==2.0.6 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2 \
--hash=sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564
urllib3==2.0.7 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84 \
--hash=sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e
xmltodict==0.13.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56 \
--hash=sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852
14 changes: 10 additions & 4 deletions src/minecraft/resource_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

import png

VALID_PACK_VERSIONS = [4, 5, 6, 7, 8, 9, 10, 12, 15, 18]
VALID_PACK_VERSIONS = [
8, # 1.18 - 1.18.2
9, # 1.19 - 1.19.2
12, # 1.19.3
15, # 1.20-1.20.1
18, # 1.20.2
]


class ResourcePack:
Expand Down Expand Up @@ -85,13 +91,13 @@ def build(self, *, verbose=False):
template_dir = os.path.join(self.__data_dir, "templates", "resourcepack")

episode_ogg = os.path.join(tmp_dir, "episode.ogg")
out_zip = os.path.join(self.__data_dir, "out", self.__output_file)
out_zip = os.path.join(
self.__data_dir, "out", f"{self.__output_file}_{self.__pack_format}"
)

# data/templates/resourcepack -> data/tmp/resourcepack
shutil.copytree(template_dir, build_dir)

# build_dir = os.path.join(tmp_dir, os.path.basename(template_dir))

# 1) Populate mcmeta template
with open(
os.path.join(template_dir, "pack.mcmeta"), encoding="utf-8"
Expand Down
77 changes: 55 additions & 22 deletions src/rss2jext.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import requests
from dotenv import load_dotenv
from ffmpeg import FFmpeg, Progress
from mutagen.oggvorbis import OggVorbis
from rss_parser import Parser
from rss_parser.models.item import Item
from rss_parser.models.types.tag import Tag
Expand All @@ -28,16 +29,16 @@ def load_servers() -> dict:
return json.load(servers_json)


def rss_latest_episode(feed_url: str) -> Tag[Item]:
def rss_feed(feed_url: str):
print(f"[RSS] Downloading feed from {feed_url}...")

# TODO: Validate RSS_URL
# TODO: Don't hardcode timeout value
feed_req = requests.get(feed_url, timeout=1000, headers={"User-Agent": USER_AGENT})
feed_req.raise_for_status()

rss = Parser.parse(feed_req.text)
return Parser.parse(feed_req.text)


def rss_latest_episode(rss) -> Tag[Item]:
print(f"[RSS] Feed language: {rss.channel.language}")
print(f"[RSS] Feed version: {rss.version}")

Expand Down Expand Up @@ -87,24 +88,40 @@ def download_mp3(url: str) -> str:
return outfile


def mp3_to_ogg(infile: str, verbose=False) -> str:
def mp3_to_ogg(infile: str, *, verbose=False) -> str:
outfile = os.path.join(__data_dir__, "tmp", "episode.ogg")
# Re-encode the audio file using ffmpeg
# ffmpeg flags to reproduce the format of vanilla records appear to be
# -c:a libvorbis -q:a 2 -ar 44100 -ac 1

aq = os.getenv("AUDIO_QUALITY")
# TODO: Check if we can pass None to options that don't take an argument (-vn)
output_settings = {
"vn": None,
"codec:a": "libvorbis",
"qscale:a": 2,
"ar": 44100,
"ac": 1,
}

if os.getenv("AUDIO_QUALITY"):
output_settings["qscale:a"] = int(os.getenv("AUDIO_QUALITY"))
print(f"[ffmpeg] qscale:a set to {output_settings['qscale:a']}")

if os.getenv("AUDIO_SAMPLERATE"):
output_settings["ar"] = int(os.getenv("AUDIO_SAMPLERATE"))
print(f"[ffmpeg] audio sample rate set to {output_settings['ar']}")

if not aq:
aq = 0
if int(os.getenv("AUDIO_NORMALIZE")):
output_settings["af"] = "loudnorm"
print("[ffmpeg] loudness normalization enabled.")

ffmpeg = (
FFmpeg()
.option("y")
.input(infile)
.output(
outfile,
{"codec:a": "libvorbis", "qscale:a": aq, "ar": 44100, "ac": 1},
output_settings,
)
)

Expand All @@ -118,6 +135,29 @@ def on_progress(progress: Progress) -> None:
return outfile


def build_packs(versions: list, *, pack_description: str):
for rp_version in versions:
print(f"[minecraft] Building resourcepack version {rp_version}...")

rp = ResourcePack(
pack_version=rp_version,
pack_description=f"Podcast About List {pack_description}",
data_dir=__data_dir__,
# shutil.make_archive appends .zip already
output_file=os.path.join(
__data_dir__, "out", str(os.getenv("RESOURCE_PACK_NAME"))
),
)

rp_filename = rp.build()
print(f"[minecraft] Resource pack built: {rp_filename}")


def build_jext_config(*, oggfile, rss_feed):
# TODO: write this. Taco Bell time yum!!!
pass


def main() -> None:
load_dotenv()

Expand All @@ -129,8 +169,10 @@ def main() -> None:
parser.add_argument("--skip-encode", action="store_true")
args = parser.parse_args()

episode = rss_latest_episode(os.getenv("RSS_URL"))
servers = load_servers()
feed = rss_feed(os.getenv("RSS_URL"))
episode = rss_latest_episode(feed)

ptero_servers = load_servers()

print(f"[RSS] Latest episode Title: {episode.title}")
print(f"[RSS] Latest episode GUID: {episode.guid}")
Expand All @@ -153,18 +195,9 @@ def main() -> None:
ogg_file = mp3_to_ogg(mp3_file)
print(f"[ffmpeg] done: {ogg_file}")

print("[minecraft] Initializing ResourcePack...")
rp = ResourcePack(
pack_version=18,
pack_description="The latest episode of Podcast About List",
data_dir=__data_dir__,
# shutil.make_archive appends .zip already
output_file=os.path.join(__data_dir__, "out", "resourcepack"),
)
build_packs([15, 18], pack_description=episode.title)

print("[minecraft] Building resource pack...")
rp_filename = rp.build()
print(f"[minecraft] Resource pack built: {rp_filename}")
audio_duration = OggVorbis(ogg_file).info.length


if __name__ == "__main__":
Expand Down

0 comments on commit 86d33b7

Please sign in to comment.