【问题标题】:How to inject caption in HLS如何在 HLS 中注入字幕
【发布时间】:2018-06-19 18:09:41
【问题描述】:

the example 中,展示了如何为 RTMP 编码的流注入字幕。

如何对 HLS 和目标 WebVTT 执行相同的操作?

【问题讨论】:

    标签: http-live-streaming wowza webvtt


    【解决方案1】:

    您可以关注这个演示(live 和 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-31
      • 1970-01-01
      • 2021-01-08
      • 2017-07-14
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多