The ffmpeg class

class audiomath.ffmpeg(destination, source=None, format=None, nChannels=None, fs=None, kbps=192, transform=None, verbose=None)

Bases: audiomath.IO.AuxiliaryBinaryInterface

This class manages the auxiliary command-line binary ffmpeg (https://ffmpeg.org ).

An instance of this class connects to the standalone ffmpeg executable, assuming that that IsInstalled(). The instance can then be used to encode audio data to disk in a variety of formats. There are two main applications, illustrated in the following examples. Both of them implicitly use ffmpeg instances under the hood:

# saving a Sound in a format other than uncompressed .wav:
import audiomath as am
s = am.TestSound( '12' )
s.Write( 'example_sound.ogg' )

# recording direct to disk:
import audiomath as am
s = am.Record(5, loop=True, filename='example_recording.mp3')

The latter example uses an ffmpeg instance as a callable hook of a Recorder instance. For more control (asynchronous functionality) you can do it more explicitly as follows:

import audiomath as am
h = am.Recorder(5, loop=True, start=False)
h.Record(hook=am.ffmpeg('example_recording.mp3', source=h, verbose=True))

h.Wait() # wait for ctrl-C (replace this line with whatever)
# ...

h.Stop(hook=None) # garbage-collection of the `ffmpeg` instance is one way to `.Close()` it
s = h.Cut()

The ffmpeg binary is large, so it is not included in the Python package by default. Installation is up to you. You can install it like any other application, somewhere on the system path. Alternatively, if you want to, you can put it directly inside the audiomath package directory, or inside a subdirectory called aux-bin—the class method ffmpeg.Install() can help you do this. If you install it inside the audiomath package, then this has two advantages: (a) audiomath will find it there when it attempts to launch it, and (b) it will be included in the output of Manifest('pyinstaller') which you can use to help you freeze your application.

Parameters:
  • destination (str, ffmpeg, sox) – output filename—be sure to include the file extension so that ffmpeg can infer the desired output format; can alternatively use another instance of ffmpeg or sox as the destination (in that case, format, nChannels and fs will also be intelligently inferred from that instance if they are not otherwise specified);
  • source (Sound, Recorder, Player, Stream) – optional instance that can intelligently specify format, nChannels and fs all in one go;
  • format (str) – format of the raw data—should be either a valid ffmpeg PCM format string (e.g. 'f32le') or a construction argument for numpy.dtype() (e.g. 'float32', '<f4');
  • nChannels (int) – number of channels to expect in each raw data packet;
  • fs (int, float) – sampling frequency, in Hz;
  • kbps (int) – kilobit rate for encoding;
  • transform (None, function) – an optional callable that can receives each data packet, along with the sample number and sampling frequency, and return a transformed version of the data packet to be send to ffmpeg in place of the original;
  • verbose (bool) – whether or not to print the standard output and standard error content produced by the binary.
exception NotInstalled(message='')

Bases: audiomath.IO.NotInstalled

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

static GrokFormat(format)

Convert a format specifier (anything that is accepted as an input to numpy.dtype()) into a string that specifies sample format in ffmpeg style (e.g. 'f32le').

classmethod Install(pathToDownloadedExecutable, deleteOriginal=False, preview=False)

Auxiliary command-line binaries (like ffmpeg or sox) can be large relative to the rest of audiomath. Therefore, they are not included in the package by default. You should download what you need from the respective project websites (e.g. https://ffmpeg.org or http://sox.sourceforge.net )

If the binary managed by this class is already installed somewhere on the operating-system’s search path, audiomath will be able to find it, so then you probably do not need this helper function. However, if you have just downloaded, say, a statically-linked build of ffmpeg.exe, are looking for somewhere to put it, and want to put it inside the audiomath package directory itself, then this function will do it for you (it will actually put it inside an automatically-created sub-directory called aux-bin). audiomath will find it there, and it will also be included in the output of Manifest('pyinstaller') which helps if you want to use pyinstaller to freeze your application.

NB: if the utility consists of multiple files (e.g. sox.exe and its many associated dll files on Windows) then pathToDownloadedExecutable should be a path to the directory that contains them all.

classmethod IsInstalled()

Return True or False depending on whether the auxiliary binary executable managed by this class (ffmpeg or sox) is accessible and executable, either inside the audiomath package (see Install()) or on the operating system’s search path.

See also: Install()

classmethod Process(snd, destination=None, **kwargs)

Whereas instances of AuxiliaryBinaryInterface subclasses are good for processing chunks of sound data sequentially, if you simply want to process a whole Sound instance in one go, it is easier to use this class method. Under the hood, it will create a temporary instance, using any specified **kwargs.

You can direct its output to the file specified by destination. Alternatively you can leave destination=None and thereby receive the output (actually written to and read back from a temporary uncompressed wav file) as a new Sound instance returned by this function.

Example, using the sox subclass:

import audiomath as am
s = am.TestSound('12')
s2 = am.sox.Process(s, effects='loudness -10')

# or, to take that example one stage further,
# the following will generally equalize the
# perceived loudness (according to ISO 226)
# across all channels of a Sound `s`:

s = am.TestSound().AutoScale()
s2 = am.Stack(
    am.sox.Process(eachChannel, effects='loudness -10')
    for eachChannel in s.SplitChannels()
).AutoScale() # finally rescale all channels together
              # according to their collective maximum