Membrane: Unable to create a source element?

Hi Guys, I’m trying to send audio from browser through phoenix channels. I’m unable to create a source element. I get this error.

➜  audio_transcription mix compile

Compiling 2 files (.ex)
    error: AudioTranscription.Source.__struct__/1 is undefined, cannot expand struct AudioTranscription.Source. Make sure the struct name is correct. If the struct name exists and is correct but it still cannot be found, you likely have cyclic module usage in your code
    │
 11 │       child(:counter, %AudioTranscription.Source{})
    │                       ^
    │
    └─ lib/audio_transcription/stream_to_file.ex:11:23: AudioTranscription.StreamToFile.handle_init/1


== Compilation error in file lib/audio_transcription/stream_to_file.ex ==
** (CompileError) lib/audio_transcription/stream_to_file.ex: cannot compile module AudioTranscription.StreamToFile (errors have been logged)
    (elixir 1.17.0) expanding macro: Kernel.|>/2

My Source element:

defmodule AudioTranscription.Source do
  use Membrane.Source

  alias Membrane.Buffer
  alias Membrane.RawAudio

  def_output_pad :output,
    availability: :always,
    accepted_format: _any,
    flow_control: :push

  @impl true
  def handle_init(_) do
    {:ok, %{buffer: []}}
  end

  @impl true
  def handle_demand(:output, size, _unit, _ctx, state) do
    {{:ok, buffer: state.buffer}, state}
  end

  def handle_playing(_ctx, state) do
    {{:ok, []}, state}
  end

  def handle_push_buffer(buffer, _ctx, state) do
    {:ok, state}
  end

  def receive_audio_data(audio_data) do
    send(self(), {:new_audio_data, audio_data})
  end

  @impl true
  def handle_info({:new_audio_data, audio_data}, _ctx, state) do
    buffer = %Buffer{payload: audio_data}
    {{:ok, buffer: {:output, buffer}}, state}
  end
end

My Pipeline

defmodule AudioTranscription.StreamToFile do
  use Membrane.Pipeline

  alias Membrane.File.Sink

  @impl true
  def handle_init(_) do
    Process.register(self(), :default_stream)

    spec =
      child(:counter, %AudioTranscription.Source{})
      |> child(%Membrane.File.Sink{location: "output.wav"})

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

  @impl true
  def send_audio_data(audio_data) do
    # Process the audio data
    AudioTranscription.AudioSource.receive_audio_data(audio_data)
  end
end

Please help, thanks

Someone from the Slack thread suggested a change:

child(:counter, %AudioTranscription.Source{})

to

child(:counter, AudioTranscription.Source)

It worked.

2 Likes