这篇文章介绍了两种方法用于从Wowza Transcoder 插件获得视频截图。要让这功能正常工作,Wowza Transcoder 必须处于正常运行状态并正在对一个视频流进行转码。
注意: 这个功能要求Wowza Media Server® 3.0.0及更高版本。
一、HTTP Provider
你可以用一个已经内建的,位于管理端口8086上的HTTP接口来从正在运行中的Wowza transcoder获得一个位图。Http URL格式如下:
http://[wowza-ip-address]:8086/transcoderthumbnail?application=[application-name]&streamname=[stream-name]&format=[jpegor png]&size=[widthxheight]
其中:
要使用这个HTTP服务,请用文本编辑器打开[install-dir]/conf/VHost.xml文件,将com.wowza.wms.transcoder.httpprovider.HTTPTranscoderThumbnail 中的 AuthenticationMethod 设置为: none。这样将关闭基于用户名和密码的认证。
接下来, 对Wowza Server进行配置,以对一个输入流进行转码。
在下面的例子中, 假定我们要转码的流为myStream,应用名为live. 要获得这个实时流的当前截图,请在WEB浏览器上访问以下URL:
http://[wowza-ip-address]:8086/transcoderthumbnail?application=live&streamname=myStream&format=jpeg&size=320x240
注意: 这个URL是区分大小写的。
日志
每一次请求截图时,你都会在[install-dir]/logs/wowzamediaserver_access.log中看到一个log消息:
commentserver INFO 200 - HTTPTranscoderThumbnail#GrabResult.onGrabFrame[live/_definst_/myStream]:Image result: format:jpeg size:320x240 timecode:107633
二、服务端 API
下面是一段代码例子,建立了莪一个名为grabFrame([stream-name])的方法,可供远程调用,获得实时流的当前截图:
package com.wowza.wms.plugin.test.module;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
import com.wowza.wms.amf.*;
import com.wowza.wms.client.*;
import com.wowza.wms.request.*;
import com.wowza.wms.module.*;
import com.wowza.wms.application.*;
import com.wowza.wms.stream.*;
import com.wowza.wms.transcoder.model.*;
import com.wowza.wms.transcoder.util.*;
public class ModuleTestTranscoderFrameGrabextends ModuleBase
{
privateIApplicationInstance appInstance = null;
classGrabResult implements ITranscoderFrameGrabResult
{
publicvoid onGrabFrame(TranscoderNativeVideoFrame videoFrame)
{
BufferedImageimage = TranscoderStreamUtils.nativeImageToBufferedImage(videoFrame);
if(image != null)
{
getLogger().info("ModuleTestTranscoderFrameGrab#GrabResult.onGrabFrame:"+image.getWidth()+"x"+image.getHeight());
StringstorageDir = appInstance.getStreamStoragePath();
FilepngFile = new File(storageDir+"/thumbnail.png");
FilejpgFile = new File(storageDir+"/thumbnail.jpg");
try
{
if (pngFile.exists())
pngFile.delete();
ImageIO.write(image,"png", pngFile);
getLogger().info("ModuleTestTranscoderFrameGrab#GrabResult.onGrabFrame:Save image: "+pngFile);
}
catch(Exceptione)
{
getLogger().error("ModuleTestTranscoderFrameGrab.grabFrame:File write error: "+pngFile);
}
try
{
if(jpgFile.exists())
jpgFile.delete();
ImageIO.write(image,"jpg", jpgFile);
getLogger().info("ModuleTestTranscoderFrameGrab#GrabResult.onGrabFrame:Save image: "+jpgFile);
}
catch(Exceptione)
{
getLogger().error("ModuleTestTranscoderFrameGrab.grabFrame:File write error: "+jpgFile);
}
}
}
}
publicvoid onAppStart(IApplicationInstance appInstance)
{
getLogger().info("ModuleTestTranscoderFrameGrab.onAppStart["+appInstance.getContextStr()+"]");
this.appInstance= appInstance;
}
publicvoid grabFrame(IClient client, RequestFunction function, AMFDataList params)
{
getLogger().info("ModuleTestTranscoderFrameGrab.grabFrame");
while(true)
{
StringstreamName = params.getString(PARAM1);
if(streamName == null)
{
getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame:No streamName");
break;
}
IApplicationInstanceappInstance = client.getAppInstance();
if(appInstance == null)
{
getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame:No appInstance");
break;
}
IMediaStreamstream = appInstance.getStreams().getStream(streamName);
if(stream == null)
{
getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame:No stream");
break;
}
LiveStreamTranscoderliveStreamTranscoder =(LiveStreamTranscoder)stream.getLiveStreamTranscoder("transcoder");
if(liveStreamTranscoder == null)
{
getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame:No liveStreamTranscoder");
break;
}
TranscoderStreamtranscodingStream = liveStreamTranscoder.getTranscodingStream();
if(transcodingStream == null)
{
getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame:No transcodingStream");
break;
}
TranscoderStreamSourceVideosourceVideo = transcodingStream.getSource().getVideo();
if(sourceVideo == null)
{
getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame:No sourceVideo");
break;
}
getLogger().info("ModuleTestTranscoderFrameGrab.grabFrame:Call grabFrame");
sourceVideo.grabFrame(newGrabResult(), 426, 240);
break;
}
}
}
要在Flash应用中调用这个方法, 先用RTMP连接到Wowza Media Server,然后用下面的方式调用:
nc.call(grabFrame, null,"[stream-name]");
其中 [stream-name] 就是你要获得截图的实时流的名字.
Wowza Streaming Engine 4是业界功能强大、API接口丰富的流媒体Server产品,采用它作为流媒体服务器产品的案例很多,直播、在线教育、IPTV都有它的用武之地。