A simple Audio I/O library written in Go. This library relies on FFmpeg, FFProbe and FFPlay which must be downloaded before usage and added to the system path.
For Video I/O using FFmpeg. see the Vidio
project.
go get github.com/AlexEidt/aio
aio
uses byte
buffers to transport raw audio data. Audio data can take on many forms, including floating point, unsigned integer and signed integer. These types may be larger than a byte
and would have to be split. Valid formats are u8
, s8
, u16
, s16
, u24
, s24
, u32
, s32
, f32
, and f64
. These represent u
unsigned integers, s
signed integers and f
floating point numbers.
As an example, if there is stereo sound (two channels) encoded in the s16
(signed 16 bit integers) format with a sampling rate of 44100 Hz
, one second of audio would be
44100 * 2 (channels) * 2 (bytes per sample) = 176400 bytes
Continuing on with this example, since this is stereo audio with 2 channels, one frame of audio is represented by 2 consecutive integers, one for each channel. Each integer is 16 bits, which means one frame of audio would be represented by 4 consecutive bytes.
The Options
struct is used to specify optional parameters for Audio I/O.
type Options struct {
Stream int // Audio Stream Index to use.
SampleRate int // Sample rate in Hz.
Channels int // Number of channels.
Bitrate int // Bitrate in bits/s.
Format string // Format of audio.
Codec string // Audio Codec.
StreamFile string // File path for extra stream data.
}
The Options.StreamFile
parameter is intended for users who wish to alter an audio stream from a video. Instead of having to process the audio and store in a file and then combine with the video later, the user can simply pass in the original video file path via the Options.StreamFile
parameter. This will combine the audio with all other streams in the given video file (Video, Subtitle, Data, and Attachments Streams) and will cut all streams to be the same length. Note that aio
is not a audio/video editing library.
This means that adding extra stream data from a file will only work if the filename
being written to is a container format, i.e attempting to add video streams to a wav
file will result in undefined behavior.
Audio
is used to read audio from files. It can also be used to gather audio metadata from a file. By default, the audio buffer has a length of
sample rate * channels * bytes per sample
which corresponds to 1 second of audio data.
The user may pass in options
to set the desired sampling rate, format and channels of the audio. If options
is nil
, then the channels and sampling rate from the file will be used, with a default format of s16
.
The Read()
function fills the internal byte buffer with the next batch of audio samples. Once the entire file has been read, Read()
will return false
and close the Audio
struct.
Note that the Samples()
function is only present for convenience. It casts the raw byte buffer into the given audio data type determined by the Format()
such that the underlying data buffers are the same. The s24
and u24
formats are not supported by the Samples()
function since there is no type equivalent. Calling the Samples()
function on 24-bit audio will return the raw byte buffer.
The return value of the Samples()
function will have to be cast into an array of the desired type (e.g. audio.Samples().([]float32)
)
aio.NewAudio(filename string, options *aio.Options) (*aio.Audio, error)
aio.NewAudioStreams(filename string, options *aio.Options) ([]*aio.Audio, error)
FileName() string
SampleRate() int
Channels() int
Bitrate() int
BitsPerSample() int
Stream() int
Total() int
Duration() float64
Format() string
Codec() string
HasStreams() bool
Buffer() []byte
MetaData() map[string]string
Samples() interface{}
SetBuffer(buffer []byte) error
Read() bool
Close()
AudioWriter
is used to write audio to files from a buffer of audio samples. It comes with an Options
struct that can be used to specify certain metadata of the output audio file. If options
is nil
, the defaults used are a sampling rate of 44100 Hz
, with 2
channels in the s16
format.
aio.NewAudioWriter(filename string, options *aio.Options) (*aio.AudioWriter, error)
FileName() string
StreamFile() string
SampleRate() int
Channels() int
Bitrate() int
Format() string
Codec() string
Write(samples interface{}) error
Close()
Microphone
is similar to the Audio
struct, the only difference being that it reads audio from the microphone. The stream
parameter is used to specify the microphone stream index, which will differ depending on the platform. For Windows (dshow
) and MacOS (avfoundation
), find the stream index by entering the following command
ffmpeg -f [dshow | avfoundation] -list_devices true -i dummy
and selecting the desired stream. For linux, see this page on the FFmpeg Wiki.
Additionally, an options
parameter may be passed to specify the format, sampling rate and audio channels the microphone should record at. Any other options are ignored.
aio.NewMicrophone(stream int, options *aio.Options) (*aio.Microphone, error)
Name() string
SampleRate() int
Channels() int
BitsPerSample() int
Format() string
Buffer() []byte
Samples() interface{}
SetBuffer(buffer []byte) error
Read() bool
Close()
Player
is used to play audio from a buffer of audio samples.
aio.NewPlayer(channels, samplerate int, format string) (*aio.Player, error)
SampleRate() int
Channels() int
Format() string
Play(samples interface{}) error
Close()
Copy input.wav
to output.mp3
.
audio, _ := aio.NewAudio("input.wav", nil)
options := aio.Options{
SampleRate: audio.SampleRate(),
Channels: audio.Channels(),
Bitrate: audio.Bitrate(),
Format: audio.Format(),
}
writer, _ := aio.NewAudioWriter("output.mp3", &options)
defer writer.Close()
for audio.Read() {
writer.Write(audio.Buffer())
}
Capture 10 seconds of audio from the microphone. Audio is recorded at 44100 Hz stereo and is in signed 16 bit format.
micOptions := aio.Options{Format: "s16", Channels: 2, SampleRate: 44100}
mic, _ := aio.NewMicrophone(0, &micOptions)
defer mic.Close()
writerOptions := aio.Options{
SampleRate: mic.SampleRate(),
Channels: mic.Channels(),
Format: mic.Format(),
}
writer, _ := aio.NewAudioWriter("output.wav", &writerOptions)
defer writer.Close()
seconds := 0
for mic.Read() && seconds < 10 {
writer.Write(mic.Buffer())
seconds++
}
Play all audio tracks from input.mp4
sequentially.
streams, _ := aio.NewAudioStreams("input.mp4", nil)
for _, stream := range streams {
player, _ := aio.NewPlayer(stream.Channels(), stream.SampleRate(), stream.Format())
for stream.Read() {
player.Play(stream.Buffer())
}
player.Close()
}
Play input.mp4
.
audio, _ := aio.NewAudio("input.mp4", nil)
player, _ := aio.NewPlayer(audio.Channels(), audio.SampleRate(), audio.Format())
defer player.Close()
for audio.Read() {
player.Play(audio.Buffer())
}
Read input.wav
and process the audio samples.
audio, _ := aio.NewAudio("input.wav", nil)
for audio.Read() {
samples := audio.Samples().([]int16)
for i := range samples {
// audio processing...
}
}
Combine sound.wav
and movie.mov
into output.mp4
.
audio, _ := aio.NewAudio("sound.wav", nil)
options := aio.Options{
SampleRate: audio.SampleRate(),
Channels: audio.Channels(),
Bitrate: audio.Bitrate(),
Format: audio.Format(),
Codec: "aac",
StreamFile: "movie.mov",
}
writer, _ := aio.NewAudioWriter("output.mp4", &options)
defer writer.Close()
for audio.Read() {
writer.Write(audio.Buffer())
}
Play Microphone audio. Use default microphone settings for recording.
mic, _ := aio.NewMicrophone(0, nil)
defer mic.Close()
player, _ := aio.NewPlayer(mic.Channels(), mic.SampleRate(), mic.Format())
defer player.Close()
for mic.Read() {
player.Play(mic.Buffer())
}