Code Monkey home page Code Monkey logo

membrane_opus_plugin's Introduction

Membrane Opus plugin

Hex.pm API Docs CircleCI

Opus encoder and decoder.

It is a part of Membrane Multimedia Framework.

Installation

The package can be installed by adding membrane_opus_plugin to your list of dependencies in mix.exs:

def deps do
  [
    {:membrane_opus_plugin, "~> 0.20.2"}
  ]
end

This package depends on libopus library. The precompiled builds will be pulled and linked automatically. However, should there be any problems, consider installing it manually.

Manual instalation of dependencies

Ubuntu

sudo apt-get install libopus-dev

Arch/Manjaro

pacman -S opus

MacOS

brew install opus

MacOS M1/M2 (Apple silicon)

On Apple M1/M2 chips, one needs to export variables:

export C_INCLUDE_PATH=$C_INCLUDE_PATH:$(brew --cellar)/opus/1.3.1/include
export LIBRARY_PATH=$LIBRARY_PATH:$(brew --cellar)/opus/1.3.1/lib

On different local setups, directory and version names may differ.

Usage

Encoder

The pipeline encodes a sample raw file and saves it as an opus file:

defmodule Membrane.ReleaseTest.Pipeline do
  use Membrane.Pipeline
  alias Membrane.RawAudio

  @input_filename "/tmp/input.raw"
  @output_filename "/tmp/output.opus"

  @impl true
  def handle_init(_ctx, _options) do
    structure = 
      child(:source, %Membrane.File.Source{
        location: @input_filename
      })
      |> child(:encoder, %Membrane.Opus.Encoder{
        application: :audio,
        input_stream_format: %RawAudio{
          channels: 2,
          sample_format: :s16le,
          sample_rate: 48_000
        }
      })
      |> child(:parser, %Membrane.Opus.Parser{delimitation: :delimit})
      |> child(:sink, %Membrane.File.Sink{
        location: @output_filename
      })

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

Opus audio generally needs to be packaged in an Ogg container in order to be played by a media player. See Membrane.Ogg.Payloader in the Membrane Ogg Plugin.

Decoder

The pipeline parses, decodes a sample opus file and then saves it as a raw file:

defmodule Membrane.ReleaseTest.Pipeline2 do
  use Membrane.Pipeline

  @input_filename "/tmp/input.raw"
  @output_filename "/tmp/output.opus"

  @impl true
  def handle_init(_ctx, _options) do
    structure = 
      child(:source, %Membrane.File.Source{
        location: @input_filename
      })
      |> child(:parser, Membrane.Opus.Parser)
      |> child(:opus, Membrane.Opus.Decoder)
      |> child(:sink, %Membrane.File.Sink{
        location: @output_filename
      })

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

Copyright and License

Copyright 2019, Software Mansion

Software Mansion

Licensed under the Apache License, Version 2.0

membrane_opus_plugin's People

Contributors

andpodob avatar bartkrak avatar bblaszkow06 avatar daniel-jodlos avatar dominikwolek avatar felonekonom avatar ixf avatar janix4000 avatar jasontrue avatar karolk99 avatar ledhed2222 avatar maksstach avatar mat-hek avatar mickel8 avatar mkaput avatar mspanc avatar mtsznowak avatar noarkhh avatar rados13 avatar roznawsk avatar varsill avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

membrane_opus_plugin's Issues

Consider getting channels and sample_rate from the stream

This can be done easily with opus functions. However, this brings the following problems:

  • a malformed packet can result in getting wrong channels/sample_rate, and to caps changes, that may not be supported by subsequent elements
  • handling such changes requires reinitializing the decoder

Test issue

This issue was created to check, if auto closing new issues works correctly

Documentation error/possible bug

The documentation on hex/in the README mentions Membrane.Opus.Serializer which was removed in commit
@ledhed2222's commit bfd5e2a on Thu Mar 18 05:30:56 2021 -0400.
The current expected process is not clear.

I was able to intuit that the serializer: Membrane.Opus.Serializer should be replaced with parser: Membrane.Opus.Parser, but if I use the pipeline with only that correction and a raw audio file (for example, captured with ffmpeg -f avfoundation -i ":1" -f s16le -c:2 -f output-s16le-48k-2ch.raw), the file that is produced doesn't appear to be playable. VLC sees it as an zero-length audio file, and opusinfo reports something like the following:

Processing file "output-s16le-48k-2ch.opus"...

WARNING: Hole in data (87 bytes) found at approximate offset 4500 bytes. Corrupted Ogg.
WARNING: Hole in data (213 bytes) found at approximate offset 4500 bytes. Corrupted Ogg.
WARNING: Hole in data (343 bytes) found at approximate offset 4500 bytes. Corrupted Ogg.
WARNING: Hole in data (413 bytes) found at approximate offset 4500 bytes. Corrupted Ogg.
WARNING: Hole in data (15 bytes) found at approximate offset 4500 bytes. Corrupted Ogg.
WARNING: Hole in data (238 bytes) found at approximate offset 4500 bytes. Corrupted Ogg.
... (much more of this)
WARNING: Hole in data (137 bytes) found at approximate offset 43424 bytes. Corrupted Ogg.
ERROR: No Ogg data found in file "output-s16le-48k-2ch.opus".
Input probably not Ogg.

I slightly modified the README example for encoding (plus some tweaks to the file paths that made sense in my case), using membrane_opus_plugin v0.10.0.

  def handle_init(_) do
    children = [
      source: %Membrane.File.Source{
        location: "/tmp/input.raw"
      },
      encoder: %Membrane.Opus.Encoder{
        application: :audio,
        input_caps: %Raw{
          channels: 2,
          format: :s16le,
          sample_rate: 48_000
        }
      },
      serializer: Membrane.Opus.Parser, ### This is where I modified the documentation example
      sink: %Membrane.File.Sink{
        location: "/tmp/output.opus"
      }
    ]

    links = [
      link(:source)
      |> to(:encoder)
      |> to(:serializer)
      |> to(:sink)
    ]

    {{:ok, spec: %ParentSpec{children: children, links: links}}, %{}}
  end
end

If it hadn't been for the unusable file at the end I'd just have submitted a documentation pull request, but I can't see a clear path to get a functional file. A similar pipeline using an MP3 plugin seemed to work just fine.

(In the event that it matters, I'm using MacOS on Intel hardware and my colleague is using an M1-based Mac).

[Codec] OPUS

This element needs a re-write almost from scratch. Things that needs to be done:

  • Declare native functions decoder.spec.exs and encoder.spec.exs - this doc chapter might be helpful. Most likely we're going to need an interface similar to FDK-AAC encoder and decoder
  • Fill encoder.h, decoder.h with state definitions
  • Implement functions declared in *.spec.exs files in proper encoder.c and decoder.c files - this will require getting familiar with libopus API. You can also take a look at the old implementation branch
  • Implement the elements: the decoder and the encoder - again, FDK-AAC might be used as reference
  • Write some tests for the element

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.