wowza java api inject captioning

狂风中的少年 提交于 2020-01-25 13:57:33

问题


We have a bunch of .mp4 files along with their associated .ttml open caption files. We are using Wowza to dynamically load and stream these files based on a dynamic schedule without interrupting the stream.

I was able to follow the tutorial here ( https://www.wowza.com/docs/how-to-use-ipublishingprovider-api-to-publish-server-side-live-streams ) to stream individual mp4 files at specified times.

However, I could not find a Java API command to inject an associated caption files. I found this page ( https://www.wowza.com/docs/how-to-configure-closed-captioning-for-live-streaming ), which doesn't talk about Java API but rather a config setting. At the end of the page was a sample package that shows some API calls, but that section was described as "legacy". I could extend that, but since it's "legacy", I fear that whatever API the module depends on may be unavailable with later versions of WMS.

Is there a low-level way (beside the "legacy" way) to tell the system to load a ttml file (or just manually inject text) immediately following a PublishingProviderMediaReader call?

Below is the code pasted from the link above

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

import com.wowza.wms.stream.publish.*;
import com.wowza.wms.vhost.*;
import com.wowza.wms.logging.*;

public class ServerPublisherWorker extends Thread
{
    private long sleepTime = 75;
    private boolean running = true;
    private Object lock = new Object();

    private String applicationName = "live";
    private String vodStreamName = "mp4:sample.mp4";
    private String liveStreamName = "myStream";
    private String publishStreamName = "publishstream";
    private int cycleTime = 10000;

    public synchronized void quit()
    {
        synchronized(lock)
        {
            running = false;
        }
    }

    public void run()
    {
        WMSLoggerFactory.getLogger(ServerPublisherWorker.class).info("ServerPublisherWorker.run: START");

        long startTime = System.currentTimeMillis();
        long playStartTime = startTime;

        try
        {
            IVHost vhost = VHostSingleton.getInstance(VHost.VHOST_DEFAULT);
            Publisher publisher = Publisher.createInstance(vhost, applicationName);

            publisher.publish(publishStreamName);

            long nextSwitch = playStartTime + cycleTime;
            long nextType = 0;
            IPublishingProvider provider = new PublishingProviderMediaReader(publisher, playStartTime, vodStreamName);
            //provider.seek(20000);
            provider.setRealTimeStartTime(startTime);

            WMSLoggerFactory.getLogger(ServerPublisherWorker.class).info("ServerPublisherWorker.run: Start with vod stream: "+vodStreamName);

            while(true)
            {
                boolean moreInFile = provider!=null?provider.play(publisher):false;

                long currentTime = System.currentTimeMillis();
                if (!moreInFile || currentTime > nextSwitch)
                {
                    if (provider != null)
                        provider.close();
                    provider = null;

                    if ((nextType % 2) == 0)
                    {
                        provider = new PublishingProviderLive(publisher, publisher.getMaxTimecode(), liveStreamName);
                        //((PublishingProviderLive)provider).setStartOnPreviousKeyFrame(false);
                        provider.setRealTimeStartTime(currentTime);

                        WMSLoggerFactory.getLogger(ServerPublisherWorker.class).info("ServerPublisherWorker.run: Switch to live stream: "+liveStreamName);
                    }
                    else
                    {
                        provider = new PublishingProviderMediaReader(publisher, publisher.getMaxTimecode(), vodStreamName);
                        //provider.seek(20000);
                        provider.setRealTimeStartTime(currentTime);

                        WMSLoggerFactory.getLogger(ServerPublisherWorker.class).info("ServerPublisherWorker.run: Switch to vod stream: "+vodStreamName);
                    }

                    nextSwitch = currentTime + cycleTime;
                    nextType++;

                    if (nextType == 100)
                        break;
                }
                else
                    sleep(sleepTime);

                synchronized(lock)
                {
                    if (!running)
                        break;
                }
            }

            provider.close();

            publisher.publish(null);

            synchronized(lock)
            {
                running = false;
            }
        }
        catch (Exception e)
        {
            WMSLoggerFactory.getLogger(ServerPublisherWorker.class).error("ServerPublisherWorker.run: "+e.toString());
            e.printStackTrace();
        }

        WMSLoggerFactory.getLogger(ServerPublisherWorker.class).info("ServerPublisherWorker.run: STOP");
    }
}

And the base listener that calls the above code:

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

import com.wowza.wms.server.*;

public class ServerPublisherServerListener implements IServerNotify
{
    ServerPublisherWorker worker = null;

    public void onServerCreate(IServer server)
    {
    }

    public void onServerInit(IServer server)
    {
        worker = new ServerPublisherWorker();
        worker.start();
    }

    public void onServerShutdownComplete(IServer server)
    {
    }

    public void onServerShutdownStart(IServer server)
    {
        if (worker != null)
            worker.quit();
        worker = null;
    }

}

Any assistance or input is much appreciated. Thank you in advance.


回答1:


You can inject cuepoints or metadata from your stream by using the following:

package com.wowza.example.module;

import com.wowza.wms.amf.*;
import com.wowza.wms.client.*;
import com.wowza.wms.module.*;
import com.wowza.wms.request.*;
import com.wowza.wms.stream.*;

public class ModuleInjectData extends ModuleBase {

    public void setCaption (IClient client, RequestFunction function, AMFDataList params)
    {
        String streamname = params.getString(PARAM1);
        String text =  params.getString(PARAM2);
        String language = params.getString(PARAM3);
        String trackid = params.getString(PARAM4);

        IMediaStream stream = client.getAppInstance().getStreams().getStream(streamname);

        //essential code
        AMFDataMixedArray data = new AMFDataMixedArray();
        data.put("text", new AMFDataItem(text));
        data.put("language", new AMFDataItem(language));
        data.put("trackid", new AMFDataItem(trackid));
        stream.sendDirect("onTextData", data);
        ((MediaStream)stream).processSendDirectMessages();
        getLogger().info("Caption: " + text);
    }

    public void injectMetaData(IClient client, RequestFunction function, AMFDataList params)
    {
        String streamName = params.getString(PARAM1);
        String data =  params.getString(PARAM2);
        IMediaStream stream = client.getAppInstance().getStreams().getStream(streamName);
        if (stream != null)
        {
            AMFDataList amfList = new AMFDataList();

            amfList.add(new AMFDataItem("@setDataFrame"));
            amfList.add(new AMFDataItem("onMetaData"));

            AMFDataMixedArray metaData = new AMFDataMixedArray();

            metaData.put("param1", data);
            metaData.put("param2", new AMFDataItem("data2"));

            amfList.add(metaData);

            synchronized(stream)
            {
                byte[] dataData = amfList.serialize();
                int size = dataData.length;
                long timecode = Math.max(stream.getAudioTC(), stream.getVideoTC());
                stream.setDataTC(timecode);
                stream.setDataSize(size);
                stream.startDataPacket();
                stream.addDataData(dataData, 0, size);
            }
        }
    }
}

You will need to create a BufferedReader object to read your file and inject the data using the above methods.



来源:https://stackoverflow.com/questions/40385566/wowza-java-api-inject-captioning

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!