Amazon EC2, Docker, Google Cloud Platform, and Microsoft Azure are available!'); //WSE Updater notice, add // to the beginning of the line below to hide //$('.hg-article, .faq-nav-wrapper').prepend('
Update your media server software installation to Wowza Streaming Engine 4.7.5.02. More Information
'); //WV REST API Deprecation Notice, add // to the beginning of the line below to hide // $('.hg-article, .faq-nav-wrapper').prepend('
The Wowza Video REST API will advance versions on September 20, 2023. v1.11 will become the current version and v1.7 will be discontinued. Additionally, v1.8 will be deprecated and JWT becomes the only auth scheme supported. See Lifecycle Management for more information. Questions? Contact Support.
'); //Wowza Flowplayer React Native SDK release notice, add // to the beginning of the line below to hide // $('.hg-article, .faq-nav-wrapper').prepend('
Wowza Flowplayer React Native SDK v1.0.0 is available! Go to the demo repository to work with the project. See the official release notes.
'); $('.hg-category-page .documentation-article, .hg-article-page .documentation-article, #search-placeholder').prepend('
\ \
\
\ '); /* off-canvas sidebar toggle */ $('[data-toggle=offcanvas]').click(function() { if ($('body').hasClass('offcanvas-article')){ Cookies.set('wowza_ko_ck_oc', '1', { path: '/' }); console.log("set cookie"); }else{ Cookies.remove('wowza_ko_ck_oc', { path: '/' }); console.log("remove cookie"); } $('.sidebar-nav').toggleClass('offcanvas'); $('.documentation-article').toggleClass('col-md-8 col-lg-9'); $('body').toggleClass('offcanvas-article'); $('#sidetoggle i').toggleClass('fa-caret-right fa-caret-left'); }); if($("#sidetoggle").length > 0) { $('body').addClass('offcanvas-body offcanvas-article'); } if (Cookies.get('wowza_ko_ck_oc') == '1'){ $('.sidebar-nav').toggleClass('offcanvas'); $('.documentation-article').toggleClass('col-md-8 col-lg-9'); $('body').toggleClass('offcanvas-article'); $('#sidetoggle i').toggleClass('fa-caret-right fa-caret-left'); } //header search engine click $( "#search-sm" ).click(function() { $('.search-menu').addClass("search-open"); //$('#search-container').animate({"right":"0px"}, 400); }); $( "#search-form").submit(function( e ) { var searchval = $( "#search-query" ).val(); e.preventDefault(); if (searchval === ""){ }else{ window.location.href='https://www.wowza.com/search#stq='+searchval+'&stp=1'; } }); $( "#search-form-mobile").submit(function( e ) { var searchval = $( "#search-query-mobile" ).val(); e.preventDefault(); if (searchval === ""){ }else{ window.location.href='https://www.wowza.com/search#stq='+searchval+'&stp=1'; } }); $('#search-mobile').click(function(){ $('.navbar-toggle').click(); }); $('#search-form-mobile-placeholder').click(function(){ $('#search-mobile-options').fadeIn(); }); $('#search-mobile-options input, search-mobile-options label ').click(function(){ var selectedText= $(this).val(); if (selectedText === "Search Support"){ $('#search-form-mobile').attr('action', '/forums/google.php'); $('#sfmpv').text('Search Support'); }else if (selectedText ==="Search Products"){ $('#search-form-mobile').attr('action', '/search'); $('#sfmpv').text('Search Products'); } $('#search-mobile-options').fadeOut(); }); $(document).click(function(event) { if(!$(event.target).closest('#search-container').length) { if($('#search-container').width() > 0) { $('.search-menu').removeClass("search-open"); } } }); //header scroll var didScroll; var lastScrollTop = 0; var delta = 100; //var navbarHeight = $('header').outerHeight(); if ($(document).scrollTop() > 0){ $('header').addClass('tiny'); $('.products-nav-shell').addClass('tiny'); $('.new-nav-shell').addClass('tiny'); $('.ko-glossary-topdiv').addClass('tiny'); } $(window).scroll(function(){ didScroll = true; }); setInterval(function() { if (didScroll) { hasScrolled(); didScroll = false; } }, 250); function hasScrolled() { var st = $(this).scrollTop(); //console.log('st:'+st+ 'last scroll top:'+lastScrollTop); if (st <= 0){ $('header').removeClass('tiny'); $('.products-nav-shell').removeClass('tiny'); $('#main-navbar').removeClass('tiny'); $('.new-nav-shell').removeClass('tiny tiny-up'); $('.ko-glossary-topdiv').removeClass('tiny'); } if(Math.abs(lastScrollTop - st) <= delta){ return; } //if (st > lastScrollTop && st > navbarHeight){ if (st > lastScrollTop){ // Scroll Down $('header').addClass('tiny'); $('#main-navbar').addClass('tiny'); $('.products-nav-shell').addClass('tiny'); $('.new-nav-shell').addClass('tiny'); $('.ko-glossary-topdiv').addClass('tiny'); $('.new-nav-shell').removeClass('tiny-up'); } else { // Scroll Up if (st>0){ $('header').removeClass('tiny'); $('.products-nav-shell').removeClass('tiny'); $('.new-nav-shell').addClass('tiny-up'); $('#main-navbar').removeClass('tiny'); $('.ko-glossary-topdiv').removeClass('tiny'); } /*if(st + $(window).height() < $(document).height()) { }*/ } lastScrollTop = st; } }); -->

Insert ID3 data events into MPEG-TS streams in Wowza Streaming Engine

This article describes how to inject ID3 data events into an MPEG-TS stream using the IRTPPacketizerMPEGTSPacketNotify interface in Wowza Streaming Engine™ media server software. The IRTPPacketizerMPEGTSPacketNotify is a simple interface that's called at initialization of an MPEG-TS packetizer and each time a new packet is processed. This notifier is a good place to inject ID3 metadata into the stream using the IRTPPacketizerMPEGTS.addDataEvent method.

Note: Wowza Streaming Engine 4.4.0 or later is required.

The following is an example of an IRTPPacketizerMPEGTSPacketNotify implementation. This example injects ID3 metadata events both on processing of incoming AMF events as well as periodically injecting events into the stream. It is two examples of how the IRTPPacketizerMPEGTS.addDataEvent method can be used:

package com.mycompany.wowza.plugin;

import java.io.*;

import com.wowza.wms.amf.*;
import com.wowza.wms.logging.*;
import com.wowza.wms.media.mp3.model.idtags.*;
import com.wowza.wms.rtp.model.*;
import com.wowza.wms.rtp.packetizer.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.vhost.*;

public class RTPPacketizerMPEGTSPacketNotifyID3Data implements IRTPPacketizerMPEGTSPacketNotify
{
    private static final Class<RTPPacketizerMPEGTSPacketNotifyID3Data> CLASS = RTPPacketizerMPEGTSPacketNotifyID3Data.class;
    private static final String CLASSNAME = "RTPPacketizerMPEGTSPacketNotifyID3Data";

    private RTPPacketizerMPEGTS rtpPacketizerMPEGTS = null;
    private long lastDataEventTC = -1;

    @Override
    public void init(RTPPacketizerMPEGTS rtpPacketizerMPEGTS, IMediaStream stream, RTPTrack rtpTrack)
    {
        WMSLoggerFactory.getLogger(CLASS).info(CLASSNAME+".init");

        this.rtpPacketizerMPEGTS = rtpPacketizerMPEGTS;

        // this will add data PID to the TS program map
        rtpPacketizerMPEGTS.setDataPID(RTPPacketizerMPEGTS.DEFAULT_PID_DATA);
    }

    @Override
    public void handleAMFPacket(OutputStream out, IMediaStream stream, RTPTrack rtpTrack, AMFPacket packet, long timecode)
    {
        int packetType = packet.getType();

        // convert AMF data events to ID3 tags and insert into the stream
        if (packetType == IVHost.CONTENTTYPE_DATA0 || packetType == IVHost.CONTENTTYPE_DATA3)
        {
            while(true)
            {
                byte[] buffer = packet.getData();
                if (buffer == null)
                    break;

                if (packet.getSize() <= 2)
                    break;

                int offset = 0;
                if (buffer[0] == 0)
                    offset++;

                AMFDataList amfList = new AMFDataList(buffer, offset, buffer.length-offset);

                if (amfList.size() <= 1)
                    break;

                if (amfList.get(0).getType() != AMFData.DATA_TYPE_STRING && amfList.get(1).getType() != AMFData.DATA_TYPE_OBJECT)
                    break;

                String metaDataStr = amfList.getString(0);
                AMFDataObj dataObj = amfList.getObject(1);

                if (!metaDataStr.equalsIgnoreCase("onTextData"))
                    break;

                AMFDataItem textData = (AMFDataItem)dataObj.get("text");
                if (textData == null)
                    break;

                String dataStr = textData.toString();
                if (dataStr == null)
                    break;

                ID3Frames id3Frames = new ID3Frames();
                ID3V2FrameTextInformation comment = new ID3V2FrameTextInformation(ID3V2FrameBase.TAG_TIT2);
                comment.setValue(dataStr);
                id3Frames.putFrame(comment);

                byte[] id3Bytes = id3Frames.serialize(true, false, ID3Frames.ID3HEADERFLAGS_DEFAULT);

                WMSLoggerFactory.getLogger(CLASS).info(CLASSNAME+".handleAMFPacket: sendDataEvent[amf]: "+dataStr);
                rtpPacketizerMPEGTS.addDataEvent(timecode, id3Bytes);
                break;
            }
        }

        // periodically insert a data event into the stream
        long currTime = System.currentTimeMillis();
        if (lastDataEventTC < 0 || (currTime-lastDataEventTC) > 1500)
        {
            if (lastDataEventTC > 0)
            {
                String dataStr = "Hello Wowza, time: "+currTime;
                ID3Frames id3Frames = new ID3Frames();
                ID3V2FrameTextInformation comment = new ID3V2FrameTextInformation(ID3V2FrameBase.TAG_TIT2);
                comment.setValue(dataStr);
                id3Frames.putFrame(comment);

                byte[] id3Bytes = id3Frames.serialize(true, false, ID3Frames.ID3HEADERFLAGS_DEFAULT);

                WMSLoggerFactory.getLogger(CLASS).info(CLASSNAME+".handleAMFPacket: sendDataEvent[async]: "+dataStr);
                rtpPacketizerMPEGTS.addDataEvent(timecode, id3Bytes);
            }
            lastDataEventTC = currTime;
        }
    }
}

To add this notifier to all out-going MPEG-TS streams for a given application, add the following custom property:

  1. In Wowza Streaming Engine Manager, click the Applications tab and then click the name of your live application in the contents panel.
     
  2. On the application page Properties tab, click Custom in the Quick Links bar.
     
    Note: Access to the Properties tab is limited to administrators with advanced permissions. For more information, see Manage credentials.
  3. In the Custom area, click Edit.
     
  4. Click Add Custom Property, specify the following settings in the Add Custom Property dialog box, and then click Add:
     
    • Path - Select /Root/Application/Streams.
       
    • Name - Enter mpegtsPacketNotifyClass.
       
    • Type - Select String.
       
    • Value - Enter com.mycompany.wowza.plugin.RTPPacketizerMPEGTSPacketNotifyID3Data.
  5. Click Save, and then restart the application to apply the changes.
The class will be instantiated for each new outgoing MPEG-TS stream.
OSZAR »