如何在HLS中注入标题

时间:2018-01-10 14:32:14

标签: hls wowza webvtt

the example中,显示了如何为RTMP编码的流注入标题。

如何为HLS和目标WebVTT做同样的事情?

1 个答案:

答案 0 :(得分:-1)

您可以按照此演示(直播和Wowza 4.4及更高版本)

基本上,这会将onTextData事件(RTMP)转换为HLS支持的ID3定时事件

package com.wowza.wms.plugin.test.module;

import java.util.*;
import com.wowza.wms.amf.*;
import com.wowza.wms.application.*;
import com.wowza.wms.httpstreamer.cupertinostreaming.livestreampacketizer.*;
import com.wowza.wms.media.mp3.model.idtags.*;
import com.wowza.wms.module.*;
import com.wowza.wms.stream.livepacketizer.*;

public class ModuleCupertinoLiveOnTextToID3 extends ModuleBase
{
    class LiveStreamPacketizerDataHandler implements IHTTPStreamerCupertinoLivePacketizerDataHandler2
    {
        private LiveStreamPacketizerCupertino liveStreamPacketizer = null;
        private int textId = 1;

        public LiveStreamPacketizerDataHandler(LiveStreamPacketizerCupertino liveStreamPacketizer)
        {
            this.liveStreamPacketizer = liveStreamPacketizer;
        }

        public void onFillChunkStart(LiveStreamPacketizerCupertinoChunk chunk)
        {
            getLogger().info("ModuleCupertinoVODOnTextToID3.onFillChunkStart["+chunk.getRendition().toString()+":"+liveStreamPacketizer.getContextStr()+"]: chunkId:"+chunk.getChunkIndexForPlaylist());

            // Add custom M3U tag to chunklist header
            CupertinoUserManifestHeaders userManifestHeaders = liveStreamPacketizer.getUserManifestHeaders(chunk.getRendition());
            if (userManifestHeaders != null)
                userManifestHeaders.addHeader("MY-USER-HEADER-DATA", "LAST-CHUNK-TIME", (new Date()).toString());

            // Add ID3 tag to start of chunk
            ID3Frames id3Frames = liveStreamPacketizer.getID3FramesHeader();
            ID3V2FrameTextInformation comment = new ID3V2FrameTextInformation(ID3V2FrameBase.TAG_TIT2);
            comment.setValue("LAST-CHUNK-TIME: "+(new Date()).toString());
            id3Frames.clear();
            id3Frames.putFrame(comment);

            textId = 1;
        }

        public void onFillChunkEnd(LiveStreamPacketizerCupertinoChunk chunk, long timecode)
        {
            getLogger().info("ModuleCupertinoVODOnTextToID3.onFillChunkEnd["+chunk.getRendition().toString()+":"+liveStreamPacketizer.getContextStr()+"]: chunkId:"+chunk.getChunkIndexForPlaylist());
        }

        public void onFillChunkMediaPacket(LiveStreamPacketizerCupertinoChunk chunk, CupertinoPacketHolder holder, AMFPacket packet)
        {

        }

        public void onFillChunkDataPacket(LiveStreamPacketizerCupertinoChunk chunk, CupertinoPacketHolder holder, AMFPacket packet, ID3Frames id3Frames)
        {
            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 textStr = textData.toString();

                getLogger().info("ModuleCupertinoVODOnTextToID3.onFillChunkDataPacket["+chunk.getRendition().toString()+":"+liveStreamPacketizer.getContextStr()+"] Send string: "+textStr);

                // Add ID3 tag with text data in chunk based on timecode order
                ID3V2FrameTextInformation comment = new ID3V2FrameTextInformation(ID3V2FrameBase.TAG_TIT2);
                comment.setValue(textStr);
                id3Frames.putFrame(comment);

                // Add custom M3U tag to chunklist just above chunk
                CupertinoUserManifestHeaders userManifestHeaders = chunk.getUserManifestHeaders();
                if (userManifestHeaders != null)
                    userManifestHeaders.addHeader("MY-USER-CHUNK-DATA-"+textId, "ON-TEXT-DATA", textStr, true);

                textId++;
                break;
            }
        }
    }

    class LiveStreamPacketizerListener extends LiveStreamPacketizerActionNotifyBase
    {
        public void onLiveStreamPacketizerCreate(ILiveStreamPacketizer liveStreamPacketizer, String streamName)
        {
            if (liveStreamPacketizer instanceof LiveStreamPacketizerCupertino)
            {
                getLogger().info("ModuleCupertinoLiveOnTextToID3#MyLiveListener.onLiveStreamPacketizerCreate["+((LiveStreamPacketizerCupertino)liveStreamPacketizer).getContextStr()+"]");
                ((LiveStreamPacketizerCupertino)liveStreamPacketizer).setDataHandler(new LiveStreamPacketizerDataHandler((LiveStreamPacketizerCupertino)liveStreamPacketizer));
            }
        }
    }

    public void onAppStart(IApplicationInstance appInstance)
    {
        appInstance.addLiveStreamPacketizerListener(new LiveStreamPacketizerListener());

        getLogger().info("ModuleCupertinoLiveOnTextToID3.onAppStart["+appInstance.getContextStr()+"]");
    }

可在此处找到更多信息: https://www.wowza.com/docs/how-to-convert-ontextdata-events-in-a-live-or-vod-stream-to-timed-events-id3-tags-in-an-apple-hls-stream