Skip to content

Commit

Permalink
Level up all audio content volume dynamically bunjlabs#18
Browse files Browse the repository at this point in the history
  • Loading branch information
bunjdo committed Mar 3, 2022
1 parent 4aef851 commit d56514e
Show file tree
Hide file tree
Showing 67 changed files with 122 additions and 35 deletions.
Binary file modified client/public/sounds/feud/beat.mp3
Binary file not shown.
Binary file modified client/public/sounds/feud/button.mp3
Binary file not shown.
Binary file modified client/public/sounds/feud/end.mp3
Binary file not shown.
Binary file modified client/public/sounds/feud/intro.mp3
Binary file not shown.
Binary file modified client/public/sounds/feud/repeat.mp3
Binary file not shown.
Binary file modified client/public/sounds/feud/right.mp3
Binary file not shown.
Binary file modified client/public/sounds/feud/round.mp3
Binary file not shown.
Binary file modified client/public/sounds/feud/timer.mp3
Binary file not shown.
Binary file modified client/public/sounds/feud/wrong.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/auction.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/bagcat.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/do_bet.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/game_end.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/intro.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/minute.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/round.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/schnelle.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/skip.mp3
Binary file not shown.
Binary file modified client/public/sounds/jeopardy/themes.mp3
Binary file not shown.
Binary file added client/public/sounds/weakest/background.mp3
Binary file not shown.
Binary file removed client/public/sounds/weakest/background.ogg
Binary file not shown.
Binary file added client/public/sounds/weakest/gong.mp3
Binary file not shown.
Binary file removed client/public/sounds/weakest/gong.ogg
Binary file not shown.
Binary file modified client/public/sounds/weakest/intro.mp3
Binary file not shown.
Binary file added client/public/sounds/weakest/question_end.mp3
Binary file not shown.
Binary file removed client/public/sounds/weakest/question_end.ogg
Binary file not shown.
Binary file added client/public/sounds/weakest/question_start.mp3
Binary file not shown.
Binary file removed client/public/sounds/weakest/question_start.ogg
Binary file not shown.
Binary file added client/public/sounds/weakest/questions.mp3
Binary file not shown.
Binary file removed client/public/sounds/weakest/questions.ogg
Binary file not shown.
Binary file modified client/public/sounds/weakest/weakest_reveal.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/black_box.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/end_defeat.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/end_victory.mp3
Binary file not shown.
Binary file added client/public/sounds/whirligig/gong.mp3
Binary file not shown.
Binary file removed client/public/sounds/whirligig/gong.ogg
Binary file not shown.
Binary file modified client/public/sounds/whirligig/intro.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/question_end_1.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/question_end_2.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/question_end_3.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/question_end_4.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/question_end_5.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/questions.mp3
Binary file not shown.
Binary file added client/public/sounds/whirligig/sig1.mp3
Binary file not shown.
Binary file removed client/public/sounds/whirligig/sig1.ogg
Binary file not shown.
Binary file added client/public/sounds/whirligig/sig2.mp3
Binary file not shown.
Binary file removed client/public/sounds/whirligig/sig2.ogg
Binary file not shown.
Binary file added client/public/sounds/whirligig/sig3.mp3
Binary file not shown.
Binary file removed client/public/sounds/whirligig/sig3.ogg
Binary file not shown.
Binary file modified client/public/sounds/whirligig/start.mp3
Binary file not shown.
Binary file modified client/public/sounds/whirligig/whirligig.mp3
Binary file not shown.
10 changes: 5 additions & 5 deletions client/src/feud/View.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import {useHistory} from "react-router-dom";
import {generateClientUrl} from "../common/View";

const Music = {
intro: HowlWrapper('/sounds/feud/intro.mp3', false, 0.5),
round: HowlWrapper('/sounds/feud/round.mp3', false, 0.5),
beat: HowlWrapper('/sounds/feud/beat.mp3', false, 0.5),
timer: HowlWrapper('/sounds/feud/timer.mp3', false, 0.5),
end: HowlWrapper('/sounds/feud/end.mp3', false, 0.5),
intro: HowlWrapper('/sounds/feud/intro.mp3'),
round: HowlWrapper('/sounds/feud/round.mp3'),
beat: HowlWrapper('/sounds/feud/beat.mp3'),
timer: HowlWrapper('/sounds/feud/timer.mp3'),
end: HowlWrapper('/sounds/feud/end.mp3'),
}

const Sounds = {
Expand Down
12 changes: 6 additions & 6 deletions client/src/weakest/View.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import {generateClientUrl} from "../common/View";

const Music = {
intro: HowlWrapper('/sounds/weakest/intro.mp3'),
background: HowlWrapper('/sounds/weakest/background.ogg', true, 0.5),
questions: HowlWrapper('/sounds/weakest/questions.ogg', true, 0.5),
background: HowlWrapper('/sounds/weakest/background.mp3'),
questions: HowlWrapper('/sounds/weakest/questions.mp3'),
}

const Sounds = {
gong: HowlWrapper('/sounds/weakest/gong.ogg'),
question_start: HowlWrapper('/sounds/weakest/question_start.ogg'),
question_end: HowlWrapper('/sounds/weakest/question_end.ogg'),
weakest_reveal: HowlWrapper('/sounds/weakest/weakest_reveal.mp3', false, 0.5),
gong: HowlWrapper('/sounds/weakest/gong.mp3'),
question_start: HowlWrapper('/sounds/weakest/question_start.mp3'),
question_end: HowlWrapper('/sounds/weakest/question_end.mp3'),
weakest_reveal: HowlWrapper('/sounds/weakest/weakest_reveal.mp3'),
}

const loadSounds = () => {
Expand Down
8 changes: 4 additions & 4 deletions client/src/whirligig/View.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ const Music = {
}

const Sounds = {
sig1: HowlWrapper('/sounds/whirligig/sig1.ogg'),
sig2: HowlWrapper('/sounds/whirligig/sig2.ogg'),
sig3: HowlWrapper('/sounds/whirligig/sig3.ogg'),
gong: HowlWrapper('/sounds/whirligig/gong.ogg'),
sig1: HowlWrapper('/sounds/whirligig/sig1.mp3'),
sig2: HowlWrapper('/sounds/whirligig/sig2.mp3'),
sig3: HowlWrapper('/sounds/whirligig/sig3.mp3'),
gong: HowlWrapper('/sounds/whirligig/gong.mp3'),
}

const loadSounds = () => {
Expand Down
2 changes: 1 addition & 1 deletion client/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module.exports = {
},
plugins:[
new webpack.DefinePlugin({
MEDIA_ENDPOINT: JSON.stringify(process.env.REACT_APP_API_ENDPOINT || "/media/"),
MEDIA_ENDPOINT: JSON.stringify(process.env.REACT_APP_MEDIA_ENDPOINT || "/media/"),
API_ENDPOINT: JSON.stringify(process.env.REACT_APP_API_ENDPOINT || "/api/"),
WS_ENDPOINT: JSON.stringify(process.env.REACT_APP_WS_ENDPOINT || "/ws/"),
}),
Expand Down
9 changes: 3 additions & 6 deletions server/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
FROM python:3.10-slim

RUN apt-get update
RUN apt-get install -y --no-install-recommends libpq-dev cron build-essential libffi-dev
RUN apt-get update && \
apt-get install -y --no-install-recommends libpq-dev build-essential libffi-dev && \
apt-get install -y ffmpeg libavcodec-extra

WORKDIR /app

Expand All @@ -13,10 +14,6 @@ RUN apt-get autoremove -y
RUN apt-get clean
RUN apt-get autoclean

COPY cron.conf /etc/cron.d/cron.conf
RUN chmod 0644 /etc/cron.d/cron.conf
RUN crontab /etc/cron.d/cron.conf

COPY . /app

CMD ["daphne", "-b", "0.0.0.0", "-p", "80", "server.asgi:application"]
Empty file.
Empty file.
37 changes: 37 additions & 0 deletions server/common/management/commands/level_up_volume.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os
import traceback

from django.core.management.base import BaseCommand
from pathlib import Path

from pydub import AudioSegment


class Command(BaseCommand):

def add_arguments(self, parser):
parser.add_argument('input', type=str)
parser.add_argument('output', type=str)

def handle(self, *args, **kwargs):
input = kwargs['input']
input_list = Path(input).rglob("*.*")
output = kwargs['output']

for path in filter(lambda p: str(p).endswith((".mp3", ".wav", ".flac", ".ogg", ".opus")), input_list):
path_str = str(path)
try:
audio = AudioSegment.from_file(path_str)
audio = audio.remove_dc_offset()

gain = audio.dBFS - (-14)
audio = audio.apply_gain(-gain)

rel = os.path.relpath(path_str, input)
filename = os.path.join(output, rel)
os.makedirs(os.path.dirname(filename), exist_ok=True)
audio.export(filename, format="mp3")

path.unlink()
except Exception:
traceback.print_exc()
37 changes: 37 additions & 0 deletions server/common/utils.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import hashlib
import os
import shutil
import string
import traceback
import typing
import zipfile
from pathlib import Path
from urllib.parse import unquote
from pydub import AudioSegment

from rest_framework.exceptions import APIException
from django.conf import settings
Expand Down Expand Up @@ -42,3 +47,35 @@ def unzip(filename, extract_dir):

def generate_token(id):
return hashids.encode(id)


def game_assets_post_process(parent: str) -> typing.Dict[str, str]:
if not settings.GAME_ASSETS_POST_PROCESS:
return {}

path_list = Path(parent).rglob('*.*')
transform_dict = {}

for path in filter(lambda p: str(p).endswith((".mp3", ".wav", ".flac", ".ogg", ".opus")), path_list):
path_str = str(path)
m = hashlib.sha256()
m.update(path_str.encode())
target_filename = m.hexdigest() + ".mp3"
target_path = os.path.join(parent, target_filename)

try:
audio = AudioSegment.from_file(path_str)

gain = audio.dBFS - (-14)
audio = audio.remove_dc_offset()
audio = audio.apply_gain(-gain)
audio = audio.compress_dynamic_range()
audio.export(target_path, format="mp3")

path.unlink()
except Exception:
traceback.print_exc()
finally:
transform_dict[os.path.relpath(path_str, parent)] = target_filename

return transform_dict
1 change: 0 additions & 1 deletion server/cron.conf

This file was deleted.

8 changes: 5 additions & 3 deletions server/jeopardy/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from rest_framework.response import Response
from rest_framework.views import APIView

from common.utils import unzip, BadStateException, BadFormatException
from common.utils import unzip, BadStateException, BadFormatException, game_assets_post_process
from jeopardy.models import Game, Player
from jeopardy.serializers import GameSerializer

Expand All @@ -31,12 +31,14 @@ def post(self, request):
path = default_storage.save(os.path.join('jeopardy', game.token, 'game'), ContentFile(data.read()))
file = os.path.join(settings.MEDIA_ROOT, path)
try:
unzip(file, os.path.join(settings.MEDIA_ROOT_JEOPARDY, game.token))
game_path = os.path.join(settings.MEDIA_ROOT_JEOPARDY, game.token)
unzip(file, game_path)
transform_dict = game_assets_post_process(game_path)
finally:
os.remove(file)

try:
game.parse(os.path.join(settings.MEDIA_ROOT_JEOPARDY, game.token, 'content.xml'))
game.parse(os.path.join(settings.MEDIA_ROOT_JEOPARDY, game.token, 'content.xml'), transform_dict)
os.remove(os.path.join(settings.MEDIA_ROOT_JEOPARDY, game.token, 'content.xml'))
except Exception as e:
shutil.rmtree(os.path.join(settings.MEDIA_ROOT_JEOPARDY, game.token), ignore_errors=True)
Expand Down
10 changes: 8 additions & 2 deletions server/jeopardy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,10 @@ def new():
return game

@transaction.atomic(savepoint=False)
def parse(self, filename):
def parse(self, filename, transform_dict=None):
if transform_dict is None:
transform_dict = {}

tree = ElementTree.parse(filename)
root = tree.getroot()

Expand All @@ -128,7 +131,10 @@ def format_image_url(url: str):

def format_audio_url(url: str):
if url and url.startswith('@'):
return '/Audio' + url.replace('@', '/', 1)
old_url = 'Audio' + url.replace('@', '/', 1)
if old_url in transform_dict:
return '/' + transform_dict[old_url]
return '/' + old_url
return url

def format_video_url(url: str):
Expand Down
2 changes: 1 addition & 1 deletion server/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ daphne==3.0.2
psycopg2-binary==2.9.1
celery==5.1.2
redis==3.5.3

pydub==0.25.1
requests==2.26.0
hashids==1.3.1
1 change: 1 addition & 0 deletions server/server/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,4 @@
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

JEOPARDY_IS_POST_EVENT_REQUIRED = False
GAME_ASSETS_POST_PROCESS = os.environ.get('GAME_ASSETS_POST_PROCESS', 'true').lower() == 'true',
8 changes: 5 additions & 3 deletions server/whirligig/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from rest_framework.response import Response
from rest_framework.views import APIView

from common.utils import unzip, BadFormatException, BadStateException
from common.utils import unzip, BadFormatException, BadStateException, game_assets_post_process
from whirligig.models import Game
from whirligig.serializers import GameSerializer

Expand All @@ -28,12 +28,14 @@ def post(self, request):
path = default_storage.save(os.path.join('whirligig', game.token, 'game'), ContentFile(data.read()))
file = os.path.join(settings.MEDIA_ROOT, path)
try:
unzip(file, os.path.join(settings.MEDIA_ROOT_WHIRLIGIG, game.token))
game_path = os.path.join(settings.MEDIA_ROOT_WHIRLIGIG, game.token)
unzip(file, game_path)
transform_dict = game_assets_post_process(game_path)
finally:
os.remove(file)

try:
game.parse(os.path.join(settings.MEDIA_ROOT_WHIRLIGIG, game.token, 'content.xml'))
game.parse(os.path.join(settings.MEDIA_ROOT_WHIRLIGIG, game.token, 'content.xml'), transform_dict)
os.remove(os.path.join(settings.MEDIA_ROOT_WHIRLIGIG, game.token, 'content.xml'))
except Exception as e:
shutil.rmtree(os.path.join(settings.MEDIA_ROOT_WHIRLIGIG, game.token), ignore_errors=True)
Expand Down
12 changes: 9 additions & 3 deletions server/whirligig/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,18 @@ def extra_time(self):
self.save()

@transaction.atomic(savepoint=False)
def parse(self, filename):
def parse(self, filename, transform_dict=None):
if transform_dict is None:
transform_dict = {}

tree = ElementTree.parse(filename)

game_xml = tree.getroot()
items_xml = game_xml.find('items')

def format_audio_url(url: str):
return '/' + transform_dict[url[1:]] if url and url.startswith('/') and url[1:] in transform_dict else url

for item_number, item_xml in enumerate(items_xml.findall('item')):
if item_number >= 13:
raise BadFormatException('Too many items')
Expand All @@ -163,13 +169,13 @@ def parse(self, filename):
description=question_xml.find('description').text,
text=question_xml.find('text').text,
image=question_xml.find('image').text,
audio=question_xml.find('audio').text,
audio=format_audio_url(question_xml.find('audio').text),
video=question_xml.find('video').text,

answer_description=answer_xml.find('description').text,
answer_text=answer_xml.find('text').text,
answer_image=answer_xml.find('image').text,
answer_audio=answer_xml.find('audio').text,
answer_audio=format_audio_url(answer_xml.find('audio').text),
answer_video=answer_xml.find('video').text,
)

Expand Down

0 comments on commit d56514e

Please sign in to comment.