Simple way to transcode mp3 to ogg in python (live)?
Asked Answered
A

1

8

I'm searching for a library / module that can transcode an MP3 (other formats are a plus) to OGG, on the fly.

What I need this for: I'm writing a relatively small web app, for personal use, that will allow people to listen their music via a browser. For the listening part, I intend to use the new and mighty <audio> tag. However, few browsers support MP3 in there. Live transcoding seems like the best option because it doesn't waste disk space (like if I were to convert the entire music library) and I will not have performance issues since there will be at most 2-3 listeners at the same time.

Basically, I need to feed it an MP3 (or whatever else) and then get a file-like object back that I can pass back to my framework (flask, by the way) to feed to the client.

Stuff I've looked at:

  • gstreamer -- seems overkill, although has good support for a lot of formats; documentation lacks horribly
  • timeside -- looks nice and simple to use, but again it has a lot of stuff I don't need (graphing, analyzing, UI...)
  • PyMedia -- last updated: 01 Feb 2006...

Suggestions?

Assumptive answered 28/3, 2011 at 20:51 Comment(0)
D
7

You know, there's no shame in using subprocess to call external utilities. For example, you could construct pipes like:

#!/usr/bin/env python
import subprocess
frommp3 = subprocess.Popen(['mpg123', '-w', '-', '/tmp/test.mp3'], stdout=subprocess.PIPE)
toogg = subprocess.Popen(['oggenc', '-'], stdin=frommp3.stdout, stdout=subprocess.PIPE)
with open('/tmp/test.ogg', 'wb') as outfile:
    while True:
        data = toogg.stdout.read(1024 * 100)
        if not data:
            break
        outfile.write(data)

In fact, that's probably your best approach anyway. Consider that on a multi-CPU system, the MP3 decoder and OGG encoder will run in separate processes and will probably be scheduled on separate cores. If you tried to do the same with a single-threaded library, you could only transcode as fast as a single core could handle it.

Deiform answered 28/3, 2011 at 21:27 Comment(6)
I've thought about this as well (I could probably get some gstreamer commands to do the same thing, with more flexibility). However, this tends to limit the portability of the app (think about trying to get it to work on Windows..). +1, though, this might end up as my solutionAssumptive
Even on Windows, I personally think it would be easier to install the mpg123 (or other decoder) and oggenc .exe's than the gstreamer framework and its Python bindings. See #2142069 for examples of that. You could even bundle the utilities with your app and add them to the installation process.Deiform
Why don't you use stdout=outfile instead of iterating by hand?Profiteer
In the original question, that would be the point in the code where he'd send the transcoded data to the client. I wanted to be verbose about reading a little bit of data at a time from the output pipe and handling it rather than waiting for the entire process to finish.Deiform
Fun fact: this wasn't my problem at all. Seems Chrome can play MP3s after all (and that will do), I just wasn't sending Content-Length and hadn't implemented range requests. (look up Range: and Content-Range: header defs).Assumptive
When i try this method I get horrible noise, with faint music in the background.Volumed

© 2022 - 2024 — McMap. All rights reserved.