Skip to content

Commit

Permalink
Merge pull request #194 from freelawproject/feat-adds-helper-method-t…
Browse files Browse the repository at this point in the history
…o-downsize-audio-files
  • Loading branch information
mlissner authored Jun 27, 2024
2 parents d959044 + 2114dc8 commit 0d34837
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 9 deletions.
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

0 comments on commit 0d34837

Please sign in to comment.