Mux Audio and Video Into WebM

This topic describes how to use the Transcoder.Run method to mux Vorbis audio and VP8 video into a WebM file.

The code snippets in this article are from the mux_webm_file .NET sample.

Source Files

For source we use the big-buck-bunny_trailer_vp8_vorbis.aud.webm and big-buck-bunny_trailer_vp8_vorbis.vid.webm files from the AVBlocks Assets repository. After downloading and unzipping you will find them in the aud and vid subdirectories.

Code

This code multiplexes two single-stream WebM files, one containing Vorbis audio and one containing VP8 video, into a WebM container file.

Initialize AVBlocks

Initialize the AVBlocks library before creating the transcoder, and shut it down after the muxing operation is complete.

var opt = new Options();

if (!opt.Prepare(args))
    return opt.Error ? (int)ExitCodes.OptionsError : (int)ExitCodes.Success;

Library.Initialize();

// Set license information. To run AVBlocks in demo mode, comment the next line out
// Library.SetLicense("<license-string>");

bool encodeResult = WebMMux(opt);

Library.Shutdown();

Create the WebM Output Socket

The output socket is configured as StreamType.WebM. The sample adds one output pin for each input audio or video stream.

using (var transcoder = new Transcoder())
{
    transcoder.AllowDemoMode = true;

    MediaSocket outputSocket = new MediaSocket();
    outputSocket.File = opt.OutputFile;
    outputSocket.StreamType = StreamType.WebM;

    // audio
    for (int i = 0; i < opt.AudioFiles.Count(); i++)
    {
        MediaPin outputPin = new MediaPin();
        AudioStreamInfo asi = new AudioStreamInfo();
        asi.StreamType = StreamType.Vorbis;
        outputPin.StreamInfo = asi;

        outputSocket.Pins.Add(outputPin);

        MediaSocket inputSocket = new MediaSocket();
        inputSocket.File = opt.AudioFiles.ElementAt(i);
        inputSocket.StreamType = StreamType.WebM;
        transcoder.Inputs.Add(inputSocket);

        Console.WriteLine("Muxing audio input: {0}", opt.AudioFiles.ElementAt(i));
    }

    // video
    for (int i = 0; i < opt.VideoFiles.Count(); i++)
    {
        MediaPin outputPin = new MediaPin();
        VideoStreamInfo vsi = new VideoStreamInfo();
        vsi.StreamType = StreamType.Vp8;
        outputPin.StreamInfo = vsi;

        outputSocket.Pins.Add(outputPin);

        MediaSocket inputSocket = new MediaSocket();
        inputSocket.File = opt.VideoFiles.ElementAt(i);
        inputSocket.StreamType = StreamType.WebM;
        transcoder.Inputs.Add(inputSocket);

        Console.WriteLine("Muxing video input: {0}", opt.VideoFiles.ElementAt(i));
    }

    transcoder.Outputs.Add(outputSocket);
    // ...
}

Run the Transcoder

After all input sockets and output pins are configured, the sample adds the output socket to the transcoder, opens it, runs the muxing operation, closes it, and prints the output file path.

transcoder.Outputs.Add(outputSocket);

if (!transcoder.Open())
{
    PrintError("Open Transcoder", transcoder.Error);
    return false;
}

if (!transcoder.Run())
{
    PrintError("Run Transcoder", transcoder.Error);
    return false;
}

transcoder.Close();

Console.WriteLine("Output file: {0}", opt.OutputFile);

return true;

Complete Code

Here’s the complete working example that demonstrates WebM muxing using AVBlocks for .NET.

using System;
using System.IO;
using System.Linq;
using PrimoSoftware.AVBlocks;

namespace CliSample
{
    class Program
    {
        static int Main(string[] args)
        {
            var opt = new Options();

            if (!opt.Prepare(args))
                return opt.Error ? (int)ExitCodes.OptionsError : (int)ExitCodes.Success;

            Library.Initialize();

            // Set license information. To run AVBlocks in demo mode, comment the next line out
            // Library.SetLicense("<license-string>");

            bool encodeResult = WebMMux(opt);

            Library.Shutdown();

            return encodeResult ? (int)ExitCodes.Success : (int)ExitCodes.EncodeError;
        }

        enum ExitCodes : int
        {
            Success = 0,
            OptionsError = 1,
            EncodeError = 2,
        }

        static void PrintError(string action, ErrorInfo e)
        {
            if (action != null)
            {
                Console.Write("{0}: ", action);
            }

            if (ErrorFacility.Success == e.Facility)
            {
                Console.WriteLine("Success");
                return;
            }
            else
            {
                Console.WriteLine("{0}, facility:{1} code:{2} hint:{3}", e.Message ?? "", e.Facility, e.Code, e.Hint ?? "");
            }
        }

        static bool WebMMux(Options opt)
        {
            try { File.Delete(opt.OutputFile); }
            catch (Exception) { }

            // Create output directory if needed
            string outputDir = Path.GetDirectoryName(opt.OutputFile);
            if (!string.IsNullOrEmpty(outputDir))
                Directory.CreateDirectory(outputDir);

            using (var transcoder = new Transcoder())
            {
                // Transcoder demo mode must be enabled,
                // in order to use the production release for testing (without a valid license)
                transcoder.AllowDemoMode = true;

                MediaSocket outputSocket = new MediaSocket();
                outputSocket.File = opt.OutputFile;
                outputSocket.StreamType = StreamType.WebM;

                // audio
                for (int i = 0; i < (int)opt.AudioFiles.Count(); i++)
                {
                    MediaPin outputPin = new MediaPin();
                    AudioStreamInfo asi = new AudioStreamInfo();
                    asi.StreamType = StreamType.Vorbis;
                    outputPin.StreamInfo = asi;

                    outputSocket.Pins.Add(outputPin);

                    MediaSocket inputSocket = new MediaSocket();
                    inputSocket.File = opt.AudioFiles.ElementAt(i);
                    inputSocket.StreamType = StreamType.WebM;
                    transcoder.Inputs.Add(inputSocket);

                    Console.WriteLine("Muxing audio input: {0}", opt.AudioFiles.ElementAt(i));
                }

                // video
                for (int i = 0; i < (int)opt.VideoFiles.Count(); i++)
                {
                    MediaPin outputPin = new MediaPin();
                    VideoStreamInfo vsi = new VideoStreamInfo();
                    vsi.StreamType = StreamType.Vp8;
                    outputPin.StreamInfo = vsi;

                    outputSocket.Pins.Add(outputPin);

                    MediaSocket inputSocket = new MediaSocket();
                    inputSocket.File = opt.VideoFiles.ElementAt(i);
                    inputSocket.StreamType = StreamType.WebM;
                    transcoder.Inputs.Add(inputSocket);

                    Console.WriteLine("Muxing video input: {0}", opt.VideoFiles.ElementAt(i));
                }

                transcoder.Outputs.Add(outputSocket);

                if (!transcoder.Open())
                {
                    PrintError("Open Transcoder", transcoder.Error);
                    return false;
                }

                if (!transcoder.Run())
                {
                    PrintError("Run Transcoder", transcoder.Error);
                    return false;
                }

                transcoder.Close();

                Console.WriteLine("Output file: {0}", opt.OutputFile);

                return true;
            }
        }
    }
}

How to Run

See the build instructions for macOS and the mux_webm_file .NET sample for details.

Command Line

mux_webm_file --audio <Vorbis_file>.webm --video <VP8_file>.webm --output <output>.webm

Examples

List options:

./bin/net10.0/mux_webm_file --help
Usage: mux_webm_file --audio <Vorbis_file>.webm --video <VP8_file>.webm --output <output>.webm
  -a,    --audio    input Vorbis/WebM files. Could be a list of files.
  -v,    --video    input VP8/WebM files. Could be a list of files.
  -o,    --output   output WebM file
  --help            Display this help screen.

Mux the WebM files big-buck-bunny_trailer_vp8_vorbis.aud.webm and big-buck-bunny_trailer_vp8_vorbis.vid.webm into the WebM file big-buck-bunny_trailer.webm:

# Linux and macOS
mkdir -p ./output/mux_webm_file

./bin/net10.0/mux_webm_file \
    --audio ./assets/aud/big-buck-bunny_trailer_vp8_vorbis.aud.webm \
    --video ./assets/vid/big-buck-bunny_trailer_vp8_vorbis.vid.webm \
    --output ./output/mux_webm_file/big-buck-bunny_trailer.webm
# Windows
mkdir -Force -Path ./output/mux_webm_file

./bin/net10.0/mux_webm_file `
    --audio ./assets/aud/big-buck-bunny_trailer_vp8_vorbis.aud.webm `
    --video ./assets/vid/big-buck-bunny_trailer_vp8_vorbis.vid.webm `
    --output ./output/mux_webm_file/big-buck-bunny_trailer.webm