Error running Membrane Pipeline tutorial

Here’s something that I got to work in IEx. (It is up to step 3.)

# Run as: iex --dot-iex path/to/notebook.exs

# Title: Membrane tutorial

Mix.install([
  :membrane_hackney_plugin,
  :membrane_mp3_mad_plugin,
  :membrane_portaudio_plugin
])

# ── Section ──

defmodule VolumeKnob do
  @moduledoc """
  Membrane filter that changes the audio volume
  by the gain passed via options.
  """
  use Membrane.Filter

  alias Membrane.RawAudio

  def_input_pad(:input, accepted_format: RawAudio, flow_control: :auto)
  def_output_pad(:output, accepted_format: RawAudio, flow_control: :auto)

  def_options(
    gain: [
      spec: float(),
      description: """
      The factor by which the volume will be changed.

      A gain smaller than 1 reduces the volume and gain
      greater than 1 increases it.
      """
    ]
  )

  @impl true
  def handle_init(_ctx, options) do
    {[], %{gain: options.gain}}
  end

  @impl true
  def handle_buffer(:input, buffer, ctx, state) do
    stream_format = ctx.pads.input.stream_format
    sample_size = RawAudio.sample_size(stream_format)

    payload =
      for <<sample::binary-size(sample_size) <- buffer.payload>>, into: <<>> do
        value = RawAudio.sample_to_value(sample, stream_format)
        scaled_value = round(value * state.gain)
        RawAudio.value_to_sample(scaled_value, stream_format)
      end

    buffer = %Membrane.Buffer{buffer | payload: payload}
    {[buffer: {:output, buffer}], state}
  end
end

defmodule MyPipeline do
  use Membrane.Pipeline

  @impl true
  def handle_init(_ctx, path_to_mp3) do
    spec =
      child(%Membrane.Hackney.Source{
        location: path_to_mp3,
        hackney_opts: [follow_redirect: true]
      })
      |> via_out(:output)
      |> via_in(:input)
      |> child(Membrane.MP3.MAD.Decoder)
      |> via_out(:output)
      |> via_in(:input)
      |> child(%VolumeKnob{gain: 0.9})
      |> via_out(:output)
      |> via_in(:input)
      |> child(Membrane.PortAudio.Sink)

    {[spec: spec], %{}}
  end
end

mp3_url =
  "https://raw.githubusercontent.com/membraneframework/membrane_demo/master/simple_pipeline/sample.mp3"

Membrane.Pipeline.start_link(MyPipeline, mp3_url)

Also, if you haven’t had a chance to check out LiveBook, it’s an amazing notebook like Jupyter is for Python. Great option for stuff you might be reaching for iex atm.

I was able to get it working in LiveBook as well. Here’s a link to download it.

MacOS 13.4.1 (c) (22F770820d)
Erlang/OTP 26 [erts-14.2.1] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns] [dtrace]
Elixir 1.16.0 (compiled with Erlang/OTP 26)