Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(audio): Add helper method to downsize audio records #194

Merged
merged 4 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,14 +311,25 @@ from courts across the country and standardizes the format for our end users.

This endpoint also adds the SEAL of the court to the MP3 file and updates the metadata to reflect our updates.

This isn't the cleanest of CURLs because we have to convert the large JSON file to a query string, but for proof of concept here is the result

curl 'http://localhost:5050/convert/audio/mp3/?audio_data=%7B%22court_full_name%22%3A+%22Testing+Supreme+Court%22%2C+%22court_short_name%22%3A+%22Testing+Supreme+Court%22%2C+%22court_pk%22%3A+%22test%22%2C+%22court_url%22%3A+%22http%3A%2F%2Fwww.example.com%2F%22%2C+%22docket_number%22%3A+%22docket+number+1+005%22%2C+%22date_argued%22%3A+%222020-01-01%22%2C+%22date_argued_year%22%3A+%222020%22%2C+%22case_name%22%3A+%22SEC+v.+Frank+J.+Custable%2C+Jr.%22%2C+%22case_name_full%22%3A+%22case+name+full%22%2C+%22case_name_short%22%3A+%22short%22%2C+%22download_url%22%3A+%22http%3A%2F%2Fmedia.ca7.uscourts.gov%2Fsound%2Fexternal%2Fgw.15-1442.15-1442_07_08_2015.mp3%22%7D' \
-X 'POST' \
-F "file=@doctor/test_assets/1.wma"

This returns the audio file as a file response.

### Endpoint: /convert/audio/ogg/

This endpoint takes an audio file and converts it to an OGG file. The conversion process downsizes files by using
a single audio channel and fixing the sampling rate to 8 kHz.

This endpoint also optimizes the output for voice over IP applications.

curl 'http://localhost:5050/convert/audio/ogg/' \
-X 'POST' \
-F "file=@doctor/test_assets/1.wma"

This returns the audio file as a file response.


## Testing

Expand Down
2 changes: 1 addition & 1 deletion doctor/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class AudioForm(BaseAudioFile):
audio_data = forms.JSONField(label="audio-data", required=False)

def clean(self):
self.cleaned_data["fp"] = f"/tmp/audio_{uuid.uuid4().hex}.mp3"
self.cleaned_data["fp"] = f"/tmp/audio_{uuid.uuid4().hex}"
if self.cleaned_data.get("file", None):
filename = self.cleaned_data["file"].name
self.cleaned_data["extension"] = filename.split(".")[-1]
Expand Down
41 changes: 41 additions & 0 deletions doctor/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,47 @@ def convert_to_mp3(output_path: AnyStr, media: Any) -> None:
return output_path


def convert_to_ogg(output_path: AnyStr, media: Any) -> None:
"""Converts audio data to the ogg format (.ogg)

This function uses ffmpeg to convert the audio data provided in `media` to
the ogg format with the following specifications:

* Single audio channel (`-ac 1`)
* 8 kHz sampling rate (`-b:a 8k`)
* Optimized for voice over IP applications (`-application voip`)

:param output_path: Audio file bytes sent to Doctor
:param media: Temporary filepath for output of audioprocess
:return:
"""
av_command = [
"ffmpeg",
"-i",
"/dev/stdin",
"-vn",
"-map_metadata",
"-1",
"-ac",
"1",
"-c:a",
"libopus",
"-b:a",
"8k",
"-application",
"voip",
"-f",
"ogg",
output_path,
]

ffmpeg_cmd = subprocess.Popen(
av_command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False
)
ffmpeg_cmd.communicate(media.read())
return output_path


def set_mp3_meta_data(
audio_data: Dict, mp3_path: AnyStr
) -> eyed3.core.AudioFile:
Expand Down
6 changes: 4 additions & 2 deletions doctor/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from django.urls import path
from django.urls import path, re_path

from . import views

Expand All @@ -23,7 +23,9 @@
views.make_png_thumbnails_from_range,
name="thumbnails",
),
path("convert/audio/mp3/", views.convert_audio, name="convert-audio"),
re_path(
"convert/audio/(mp3|ogg)/", views.convert_audio, name="convert-audio"
),
path("utils/page-count/pdf/", views.page_count, name="page_count"),
path("utils/mime-type/", views.extract_mime_type, name="mime_type"),
path(
Expand Down
18 changes: 14 additions & 4 deletions doctor/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from doctor.tasks import (
convert_tiff_to_pdf_bytes,
convert_to_mp3,
convert_to_ogg,
download_images,
extract_from_doc,
extract_from_docx,
Expand Down Expand Up @@ -367,8 +368,11 @@ def fetch_audio_duration(request) -> HttpResponse:
return HttpResponse(str(e))


def convert_audio(request) -> Union[FileResponse, HttpResponse]:
"""Convert audio file to MP3 and update metadata on mp3.
def convert_audio(
request, output_format: str
) -> Union[FileResponse, HttpResponse]:
"""Converts an uploaded audio file to the specified output format and
updates its metadata.

:return: Converted audio
"""
Expand All @@ -378,8 +382,14 @@ def convert_audio(request) -> Union[FileResponse, HttpResponse]:
filepath = form.cleaned_data["fp"]
media_file = form.cleaned_data["file"]
audio_data = {k: v[0] for k, v in dict(request.GET).items()}
convert_to_mp3(filepath, media_file)
set_mp3_meta_data(audio_data, filepath)
match output_format:
case "mp3":
convert_to_mp3(filepath, media_file)
set_mp3_meta_data(audio_data, filepath)
case "ogg":
convert_to_ogg(filepath, media_file)
case _:
raise NotImplemented
response = FileResponse(open(filepath, "rb"))
cleanup_form(form)
return response
Expand Down
Loading