流媒体技术世界——分享技术,增值服务
如何从Wowza transcoder获得实时流的视频截图?
这篇文章介绍了两种方法用于从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=[jpeg or png]&size=[widthxheight]
其中:
  • [wowza-ip-address]: 运行Wowza Server的服务器IP地址
  • application-name: 应用名
  • stream-name: 输入流的stream name. 不要用转码后的输出流的名字或StreamNameGroup的名字.
  • format: 图片的格式:jpeg 或 png
  • size: 截图的大小.如果没有设置,则会按一帧图像的完整大小返回


要使用这个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消息:
comment	server	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 ModuleTestTranscoderFrameGrab extends ModuleBase
{
	private IApplicationInstance appInstance = null;
	
	class GrabResult implements ITranscoderFrameGrabResult
	{
		public void onGrabFrame(TranscoderNativeVideoFrame videoFrame)
		{			
			BufferedImage image = TranscoderStreamUtils.nativeImageToBufferedImage(videoFrame);
			if (image != null)
			{
			
				getLogger().info("ModuleTestTranscoderFrameGrab#GrabResult.onGrabFrame: "+image.getWidth()+"x"+image.getHeight());
				
				String storageDir = appInstance.getStreamStoragePath();
				
				File pngFile = new File(storageDir+"/thumbnail.png");
				File jpgFile = 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(Exception e)
				{
					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(Exception e)
				{
					getLogger().error("ModuleTestTranscoderFrameGrab.grabFrame: File write error: "+jpgFile);
				}
			}
		}
	}
	
	public void onAppStart(IApplicationInstance appInstance)
	{
		getLogger().info("ModuleTestTranscoderFrameGrab.onAppStart["+appInstance.getContextStr()+"]");
		this.appInstance = appInstance;
	}
	
	public void grabFrame(IClient client, RequestFunction function, AMFDataList params)
	{
		getLogger().info("ModuleTestTranscoderFrameGrab.grabFrame");

		while(true)
		{
			String streamName = params.getString(PARAM1);
			if (streamName == null)
			{
				getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame: No streamName");
				break;
			}
			
			IApplicationInstance appInstance = client.getAppInstance();
			if (appInstance == null)
			{
				getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame: No appInstance");
				break;
			}
			
			IMediaStream stream = appInstance.getStreams().getStream(streamName);
			if (stream == null)
			{
				getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame: No stream");
				break;
			}
			
			LiveStreamTranscoder liveStreamTranscoder = (LiveStreamTranscoder)stream.getLiveStreamTranscoder("transcoder");
			if (liveStreamTranscoder == null)
			{
				getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame: No liveStreamTranscoder");
				break;
			}
			
			TranscoderStream transcodingStream = liveStreamTranscoder.getTranscodingStream();
			if (transcodingStream == null)
			{
				getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame: No transcodingStream");
				break;
			}
			
			TranscoderStreamSourceVideo sourceVideo = transcodingStream.getSource().getVideo();
			if (sourceVideo == null)
			{
				getLogger().warn("ModuleTestTranscoderFrameGrab.grabFrame: No sourceVideo");
				break;
			}
			
			getLogger().info("ModuleTestTranscoderFrameGrab.grabFrame: Call grabFrame");
			sourceVideo.grabFrame(new GrabResult(), 426, 240);
			break;
		}
	}
}
了解更多Wowza产品细节
要在Flash应用中调用这个方法, 先用RTMP连接到Wowza Media Server,然后用下面的方式调用:
nc.call(grabFrame, null, "[stream-name]");
其中 [stream-name] 就是你要获得截图的实时流的名字.

匿名用户
评论

我们的地址


北京市朝阳区管庄西里建基商务楼423室


邮编:100024

关于我们


北京联方信科信息技术有限责任公司


官网:www.ttstream.com

联系我们


王经理:phone


柳经理:phone

京ICP备14033868号-2