Skip to content

Commit ca4b9d6

Browse files
committed
use ffmpeg to generate waveform images for audio thumbnailsources
1 parent 9835734 commit ca4b9d6

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ classifiers = [
1313
]
1414
dependencies = [
1515
"exifread==3.0.0",
16+
"ffmpeg-python==0.2.0",
1617
"httpx==0.27.2",
1718
"opencv-python==4.10.0.84",
1819
"pillow==11.0.0",

src/bma_client_lib/bma_client.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import cv2
1515
import exifread
16+
import ffmpeg
1617
import httpx
1718
import magic
1819
import pymupdf
@@ -186,6 +187,17 @@ def _handle_thumbnail_source_job(self, job: ThumbnailSourceJob, fileinfo: dict[s
186187
exif[0x131] = self.clientinfo["client_version"]
187188
job.exif = exif
188189
return
190+
if fileinfo["filetype"] == "audio":
191+
# use ffmpeg to generate a picture of the waveform
192+
ss = self._get_audio_screenshot(job=job)
193+
job.images = [ss]
194+
exif = Image.Exif()
195+
exif[0x100] = job.images[0].width
196+
exif[0x101] = job.images[0].height
197+
exif[0x10E] = f"ThumbnailSource for BMA audio file {job.basefile_uuid}"
198+
exif[0x131] = self.clientinfo["client_version"]
199+
job.exif = exif
200+
return
189201

190202
# unsupported filetype
191203
raise JobNotSupportedError(job=job)
@@ -217,6 +229,19 @@ def _get_document_screenshot(self, job: ThumbnailSourceJob, page: int = 0) -> Im
217229
pix = pdfpage.get_pixmap()
218230
return Image.frombytes("RGB", (pix.width, pix.height), pix.samples)
219231

232+
def _get_audio_screenshot(self, job: ThumbnailSourceJob) -> Image.Image:
233+
"""Get a waveform screenshot. Requires ffmpeg as external dep."""
234+
path = self.path / job.source_url[1:]
235+
output, _ = (
236+
ffmpeg.input(str(path))
237+
.filter("compand")
238+
.filter("showwavespic", s="1000x1000", split_channels=1)
239+
.output("pipe:", format="webp", vframes="1")
240+
# .overwrite_output()
241+
.run(capture_stdout=True)
242+
)
243+
return Image.open(BytesIO(output))
244+
220245
###############################################################################
221246

222247
def _write_and_upload_result(self, job: Job, filename: str) -> None:

0 commit comments

Comments
 (0)