Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

KinoMembrane

livebooks/kino/kino_membrane.livemd

KinoMembrane

Mix.install([
  {:kino, "~> 0.13", override: true},
  {:kino_membrane, "~> 0.3"},
  {:membrane_hackney_plugin, "~> 0.11"},
  {:membrane_ffmpeg_swresample_plugin, "~> 0.20"},
  {:membrane_mp3_mad_plugin, "~> 0.18"},
  {:membrane_aac_fdk_plugin, "~> 0.18"},
  {:membrane_audio_mix_plugin, "~> 0.16"},
  {:membrane_tee_plugin, "~> 0.12"},
  {:membrane_kino_plugin,
   github: "membraneframework-labs/membrane_kino_plugin", tag: "v0.3.2"}
])

Play MP3

import Membrane.ChildrenSpec

alias Membrane.{
  AAC,
  AudioMixer,
  Hackney,
  MP3,
  RawAudio,
  RCPipeline,
  Tee,
  Time
}

alias Membrane.FFmpeg.SWResample.Converter
kino = Membrane.Kino.Player.new(audio: true)
base_repo_url = "https://raw.githubusercontent.com/membraneframework/membrane_demo/master"

source_url = "#{base_repo_url}/simple_pipeline/sample.mp3"
pipeline = RCPipeline.start_link!()

spec =
  child(:hackney, %Hackney.Source{
    location: source_url,
    hackney_opts: [follow_redirect: true]
  })
  |> via_in(:input, auto_demand_size: 10)
  |> child(:decoder, MP3.MAD.Decoder)
  |> child(:converter, %Converter{
    output_stream_format: %RawAudio{
      sample_format: :s16le,
      sample_rate: 48000,
      channels: 2
    }
  })
  |> child(:encoder_aac, AAC.FDK.Encoder)
  |> via_in(:audio)
  |> child(:player, %Membrane.Kino.Player.Sink{kino: kino})
RCPipeline.exec_actions(pipeline, spec: spec)
KinoMembrane.pipeline_dashboard(pipeline)
Membrane.Pipeline.terminate(pipeline)

Mixing audio files

beep_url = "#{base_repo_url}/livebooks/audio_mixer/assets/beep.aac"

beep_audio_input =
  child(:beep_hackney, %Hackney.Source{
    location: beep_url,
    hackney_opts: [follow_redirect: true]
  })
  |> child({:beep_decoder_aac, :beep}, AAC.FDK.Decoder)
  |> child(:beeps, Tee.PushOutput)
n_beeps = 30

beeps_split =
  for i <- 1..n_beeps do
    get_child(:beeps)
    |> via_in(:input, options: [offset: Time.seconds(i)])
    |> get_child(:mixer)
  end
background_url = "#{base_repo_url}/livebooks/audio_mixer/assets/sample.mp3"

background_audio_input =
  child(:background_hackney, %Hackney.Source{
    location: background_url,
    hackney_opts: [follow_redirect: true]
  })
  |> child(:background_decoder_mp3, MP3.MAD.Decoder)
  |> child(:background_converter, %Converter{
    input_stream_format: %RawAudio{channels: 2, sample_format: :s24le, sample_rate: 48_000},
    output_stream_format: %RawAudio{channels: 1, sample_format: :s16le, sample_rate: 44_100}
  })
  |> get_child(:mixer)
mixer_kino = Membrane.Kino.Player.new(audio: true)
mixer_output =
  child(:mixer, AudioMixer)
  |> child(:mixer_encoder_aac, AAC.FDK.Encoder)
  |> via_in(:audio)
  |> child(:mixer_player, %Membrane.Kino.Player.Sink{kino: mixer_kino})
mixer_spec = beeps_split ++ [beep_audio_input, background_audio_input, mixer_output]
mixer_pipeline = RCPipeline.start_link!()

RCPipeline.exec_actions(mixer_pipeline, spec: mixer_spec)
KinoMembrane.pipeline_dashboard(mixer_pipeline)
Membrane.Pipeline.terminate(mixer_pipeline)