2016-11-02 39 views
0

我们有一堆.mp4文件及其关联的.ttml打开的字幕文件。我们正在使用Wowza来动态加载和流式传输这些文件,而不会中断流。wowza java api注入字幕

我能够按照教程在这里(https://www.wowza.com/docs/how-to-use-ipublishingprovider-api-to-publish-server-side-live-streams)在指定的时间流个别mp4文件。

但是,我找不到一个Java API命令来注入关联的标题文件。我找到了这个页面(https://www.wowza.com/docs/how-to-configure-closed-captioning-for-live-streaming),它没有谈论Java API,而是一个配置设置。在页面的最后是一个示例包,显示了一些API调用,但该部分被描述为“遗留”。我可以扩展它,但由于它是“遗留”,所以我担心模块依赖的任何API可能在更高版本的WMS中不可用。

在PublishingProviderMediaReader调用之后,是否有一种低级方式(在“传统”方式旁边)告诉系统加载ttml文件(或者只是手动注入文本)?

下面是从链接粘贴上述

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"); 
    } 
} 

代码并调用上述代码的基础听者:

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; 
    } 

} 

任何援助或输入是非常赞赏。先谢谢你。

回答

1

您可以通过以下注入中cuePoints或元数据,从信息流:

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); 
      } 
     } 
    } 
} 

你需要创建一个BufferedReader对象来读取文件并注入使用上述方法中的数据。

+0

谢谢。 setCaption函数直接放入并为rtmp工作 – nanytech