Mux Audio and Video Into MP4

This topic describes how to use the Transcoder class to mux AAC audio and H.264 video into an MP4 file.

mux_mp4_avc_aac_file Sample

The code snippets in this article are from the mux_mp4_avc_aac_file sample app. The complete source code of the mux_mp4_avc_aac_file app is available in the following BitBucket repositories:

.NET

Complete .NET code

static bool MP4Mux(Options opt)
{
    bool audioStreamDetected = false;
    bool videoStreamDetected = false;

    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;

        // configure inputs
        foreach (string inputFile in opt.InputFiles)
        {
            using (MediaInfo info = new MediaInfo())
            {
                info.InputFile = inputFile;

                if (!info.Load())
                {
                    PrintError("mediaInfo.Load", info.Error);
                    return false;
                }

                MediaSocket inputSocket = MediaSocket.FromMediaInfo(info);

                for (int i = 0; i < inputSocket.Pins.Count; i++)
                {
                    MediaPin pin = inputSocket.Pins[i];

                    if(pin.StreamInfo.StreamType == StreamType.H264)
                    {
                        if(videoStreamDetected)
                        {
                            pin.Connection = PinConnection.Disabled;
                        }
                        else
                        {
                            videoStreamDetected = true;
                            Console.WriteLine("Muxing video input: {0}", inputFile);
                        }
                    }
                    else if(pin.StreamInfo.StreamType == StreamType.Aac)
                    {
                        if(audioStreamDetected)
                        {
                            pin.Connection = PinConnection.Disabled;
                        }
                        else
                        {
                            audioStreamDetected = true;
                            Console.WriteLine("Muxing audio input: {0}", inputFile);
                        }
                    }
                    else
                    {
                        pin.Connection = PinConnection.Disabled;
                    }
                }

                transcoder.Inputs.Add(inputSocket);
            }
        }

        // Configure output
        {
            MediaSocket socket = new MediaSocket();
            socket.File = opt.OutputFile;
            socket.StreamType = StreamType.Mp4;

            if(videoStreamDetected)
            {
                VideoStreamInfo streamInfo = new VideoStreamInfo();
                streamInfo.StreamType = StreamType.H264;
                streamInfo.StreamSubType = StreamSubType.Avc1;

                MediaPin pin = new MediaPin();
                pin.StreamInfo = streamInfo;
                socket.Pins.Add(pin);
            }

            if (audioStreamDetected)
            {
                AudioStreamInfo streamInfo = new AudioStreamInfo();
                streamInfo.StreamType = StreamType.Aac;
                streamInfo.StreamSubType = StreamSubType.AacMp4;

                MediaPin pin = new MediaPin();
                pin.StreamInfo = streamInfo;
                socket.Pins.Add(pin);
            }

            if(opt.FastStart)
            {
                socket.Params.Add(Param.Muxer.MP4.FastStart, 1);
            }

            transcoder.Outputs.Add(socket);
        }

        bool res = transcoder.Open();
        PrintError("Open Transcoder", transcoder.Error);
        if (!res)
            return false;

        res = transcoder.Run();
        PrintError("Run Transcoder", transcoder.Error);
        if (!res)
            return false;

        transcoder.Close();
    }

    return true;
}

C++

Complete C++ code

bool MP4Mux(const Options& opt)
{
    auto transcoder = primo::make_ref(Library::createTranscoder());

    // Transcoder demo mode must be enabled, 
    // in order to use the production release for testing (without a valid license)
    transcoder->setAllowDemoMode(TRUE);

    bool audioStreamDetected = false;
    bool videoStreamDetected = false;

    for(int i = 0; i < (int)opt.input_files.size(); i++)
    {
        auto mediaInfo = primo::make_ref(Library::createMediaInfo());
        mediaInfo->setInputFile(opt.input_files[i].c_str());

        if (!mediaInfo->load())
        {
            printError(L"mediaInfo.Load", mediaInfo->error());
            return false;
        }

        auto inputSocket = primo::make_ref(Library::createMediaSocket(mediaInfo.get()));

        for(int j = 0; j < inputSocket->pins()->count(); j++)
        {
            MediaPin *pin = inputSocket->pins()->at(j);

            if(pin->streamInfo()->streamType() == StreamType::H264)
            {
                if(videoStreamDetected)
                {
                    pin->setConnection(PinConnection::Disabled);
                }
                else
                {
                    videoStreamDetected = true;
                    wcout << "Muxing video input: " << opt.input_files[i] << std::endl;
                }
            }
            else if(pin->streamInfo()->streamType() == StreamType::AAC)
            {
                if(audioStreamDetected)
                {
                    pin->setConnection(PinConnection::Disabled);
                }
                else
                {
                    audioStreamDetected = true;
                    wcout << "Muxing audio input: " << opt.input_files[i] << std::endl;
                }
            }
            else
            {
                pin->setConnection(PinConnection::Disabled);
            }
        }

        transcoder->inputs()->add(inputSocket.get());
    }

    // Configure output
    {
        auto socket = primo::make_ref(Library::createMediaSocket());
        socket->setFile(opt.output_file.c_str());
        socket->setStreamType(StreamType::MP4);

        if(videoStreamDetected)
        {
            auto streamInfo = primo::make_ref(Library::createVideoStreamInfo());
            streamInfo->setStreamType(StreamType::H264);
            streamInfo->setStreamSubType(StreamSubType::AVC1);

            auto pin = primo::make_ref(Library::createMediaPin());
            pin->setStreamInfo(streamInfo.get());
            socket->pins()->add(pin.get());
        }

        if(audioStreamDetected)
        {
            auto streamInfo = primo::make_ref(Library::createAudioStreamInfo());
            streamInfo->setStreamType(StreamType::AAC);
            streamInfo->setStreamSubType(StreamSubType::AAC_MP4);

            auto pin = primo::make_ref(Library::createMediaPin());
            pin->setStreamInfo(streamInfo.get());
            socket->pins()->add(pin.get());
        }

        if(opt.fast_start)
        {
            socket->params()->addInt(Param::Muxer::MP4::FastStart, 1);
        }

        transcoder->outputs()->add(socket.get());
    }

    bool_t res = transcoder->open();
    printError(L"Open Transcoder", transcoder->error());
    if (!res)
        return false;

    res = transcoder->run();
    printError(L"Run Transcoder", transcoder->error());

    transcoder->close();

    return res ? true : false;
}


Last updated on April 8th, 2017 02:55:54 PM