背景:在已有的red5服务器环境下实现android客户端的视频直播
要实现客户端视频直播就先先对服务器端有所了解
Red5流媒体服务器是Adboe的产品,免费并且是开源的,与Flash搭配的时候可谓是天生一对,但使用Java和Android作为客户端调用却可谓一波三折。
Red5是一个采用Java开发开源的Flash流媒体服务器。它支持:把音频(MP3)和视频(FLV)转换成播放流; 录制客户端播放流(只支持FLV);共享对象;现场直播流发布;远程调用。Red5使用RSTP作为流媒体传输协议,在其自带的一些示例中演示了在线录制,flash流媒体播放,在线聊天,视频会议等一些基本功能。
服务器的相关配置
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/FlashMediaGateway</param-value>
</context-param>
[root@lapaccweb WEB-INF]# more red5-web.properties
webapp.contextPath=/FlashMediaGateway
webapp.virtualHosts=*:1935,*:443
recordPath=/opt/Avaya/AccWeb/data/SessionRecording/
playbackPath=/opt/Avaya/AccWeb/data/SessionRecording/
absolutePath=true
Adobe的Red5源代码里有一个RTMPClient的类,这个类在使用上其实不复杂,但却没办法成功调用。观察日志,发现是连接成功后在开始创建流的时候,服务端把连接断开了。我能想到的解释就是可能公司现在所使用的Red5服务器的版本与这个RTMPClient不兼容。
国外还有一个收费的RTMPClient,价值是395刀。具体网址和产品的名称我就不指出了,有心人肯定会找得到。这个客户端类库很强大,使用也很方便,我注册了一个试用的key,发现能和Red5服务器成功连接并且通讯良好。(国内有破解版)
之前用vlc和Vitamio尝试过,结果播放不了直播流,可能是我太笨了吧.
有可能的原因如下:
http://blog.csdn.net/qiuchangyong/article/details/18862247
利用LocalServerSocket采集视频数据的实时流数据,android自带的LocalServerSocket是和java 的serverSocket是不同的,因为LocalServerSocket的客户端和服务端都是必须在本机,所以我们可以在调用RecodMedia录制视频的时候建立客户端LocalSocket来向服务端发送数据,在服务端接收数据调用juv—rtmp—client将接收的数据打包成RTMP协议数据向流媒体服务器发送数据。
利用android自带的Camera来录制数据,这里主要用到了照相机的CallBack回调接口,在这个回调接口里面可以实时的接收照相机录制的视频数据,这里面录制的视频数据是YUV420SP格式的数据流,这是最原始的数据流,是无法显示的服务器界面的。将数据流转化成YUV420SP2RGB格式的数据,然后利用juv—rtmp—client向流媒体服务器发送数据。
juv—rtmp—client这个jar包封装了很多和流媒体服务器交互的方法,当然有视频数据传输格式。在流媒体服务提供了三种格式的传输方式:Record、Live、Append。
利用juv—rtmp—client有几个主要的类
其中最重要的几个类是NetConnection,NetStream, License,其中NetConnection,NetStream这两个类是负责创建连接和回调服务端的数据。而License则顾名思义是负责验证有没有授权。由于按照官方给出的使用说明,在使用前必须调用License.setKey()方法传入注册所得到的key。
CameraVideoActivity
private void init() {
aCamera = new AndroidCamera(CameraVideoActivity.this);
hour = (TextView) findViewById(R.id.mediarecorder_TextView01);
minute = (TextView) findViewById(R.id.mediarecorder_TextView03);
second = (TextView) findViewById(R.id.mediarecorder_TextView05);
mStart = (Button) findViewById(R.id.mediarecorder_VideoStartBtn);
mStop = (Button) findViewById(R.id.mediarecorder_VideoStopBtn);
mReturn = (Button) findViewById(R.id.mediarecorder_VideoReturnBtn);
// 开始录像
mStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (streaming == false) {
aCamera.start();
}
aCamera.startVideo();
isTiming = true;
handler.postDelayed(task, 1000);
// 设置按钮状态
mStart.setEnabled(false);
mReturn.setEnabled(false);
mStop.setEnabled(true);
}
});
mReturn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (RTMPConnectionUtil.netStream != null) {
RTMPConnectionUtil.netStream.close();
RTMPConnectionUtil.netStream = null;
}
if (aCamera != null) {
aCamera = null;
}
finish();
}
});
mStop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
aCamera.stop();
// 设置按钮状态
mStart.setEnabled(true);
mReturn.setEnabled(true);
mStop.setEnabled(false);
isTiming = false;
}
});
}
public class AndroidCamera extends AbstractCamera implements
SurfaceHolder.Callback, Camera.PreviewCallback {
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Camera camera;
private int width;
private int height;
private boolean init;
int blockWidth;
int blockHeight;
int timeBetweenFrames; // 1000 / frameRate
int frameCounter;
byte[] previous;
public AndroidCamera(Context context) {
surfaceView = (SurfaceView) findViewById(R.id.mediarecorder_Surfaceview);
surfaceView.setVisibility(View.VISIBLE);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(AndroidCamera.this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
width = 352 / 2;
height = 288 / 2;
init = false;
Log.d("DEBUG", "AndroidCamera()");
}
private void startVideo() {
Log.d("DEBUG", "startVideo()");
RTMPConnectionUtil.ConnectRed5(CameraVideoActivity.this);
RTMPConnectionUtil.netStream = new UltraNetStream(
RTMPConnectionUtil.connection);
RTMPConnectionUtil.netStream
.addEventListener(new NetStream.ListenerAdapter() {
@Override
public void onNetStatus(final INetStream source,
final Map<String, Object> info) {
Log.d("DEBUG", "Publisher#NetStream#onNetStatus: "
+ info);
final Object code = info.get("code");
if (NetStream.PUBLISH_START.equals(code)) {
if (CameraVideoActivity.aCamera != null) {
RTMPConnectionUtil.netStream
.attachCamera(aCamera, -1 /* snapshotMilliseconds */);
Log.d("DEBUG", "aCamera.start()");
aCamera.start();
} else {
Log.d("DEBUG", "camera == null");
}
}
}
});
RTMPConnectionUtil.netStream.publish("anystringdata", NetStream.LIVE);
}
public void start() {
camera.startPreview();
streaming = true;
}
public void stop() {
camera.stopPreview();
streaming = false;
}
public void printHexString(byte[] b) {
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
}
}
@Override
public void onPreviewFrame(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
// if (!active) return;
if (!init) {
blockWidth = 32;
blockHeight = 32;
timeBetweenFrames = 100; // 1000 / frameRate
frameCounter = 0;
previous = null;
init = true;
}
final long ctime = System.currentTimeMillis();
/** 将采集的YUV420SP数据转换为RGB格式 */
byte[] current = RemoteUtil.decodeYUV420SP2RGB(arg0, width, height);
try {
//
final byte[] packet = RemoteUtil.encode(current, previous,
blockWidth, blockHeight, width, height);
fireOnVideoData(new MediaDataByteArray(timeBetweenFrames,
new ByteArray(packet)));
previous = current;
if (++frameCounter % 10 == 0)
previous = null;
} catch (Exception e) {
e.printStackTrace();
}
final int spent = (int) (System.currentTimeMillis() - ctime);
try {
Thread.sleep(Math.max(0, timeBetweenFrames - spent));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
// camera.startPreview();
// camera.unlock();
// Log.d("DEBUG", "surfaceChanged()");
// startVideo();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
try {
camera.setPreviewDisplay(surfaceHolder);
camera.setPreviewCallback(this);
Camera.Parameters params = camera.getParameters();
params.setPreviewSize(width, height);
camera.setParameters(params);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
camera.release();
camera = null;
}
Log.d("DEBUG", "surfaceCreated()");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}
}
}
/* 定时器设置,实现计时 */
private Handler handler = new Handler();
int s, h, m, s1, m1, h1;
private Runnable task = new Runnable() {
public void run() {
if (isTiming) {
handler.postDelayed(this, 1000);
s++;
if (s < 60) {
second.setText(format(s));
} else if (s < 3600) {
m = s / 60;
s1 = s % 60;
minute.setText(format(m));
second.setText(format(s1));
} else {
h = s / 3600;
m1 = (s % 3600) / 60;
s1 = (s % 3600) % 60;
hour.setText(format(h));
minute.setText(format(m1));
second.setText(format(s1));
}
}
}
};
RTMPConnectionUtil
public static void ConnectRed5(Context context) {
// License.setKey("63140-D023C-D7420-00B15-91FC7");
connection = new UltraNetConnection();
connection.configuration().put(UltraNetConnection.Configuration.INACTIVITY_TIMEOUT, -1);
connection.configuration().put(UltraNetConnection.Configuration.RECEIVE_BUFFER_SIZE, 256 * 1024);
connection.configuration().put(UltraNetConnection.Configuration.SEND_BUFFER_SIZE, 256 * 1024);
//connection.client(new ClientHandler(context));
connection.addEventListener(new NetConnectionListener());
//Log.d("DEBUG", User.id + " - " + User.phone);
connection.connect(red5_url);
}
附带一款测试Red5用rtmp是否能够连接工具
博客地址:http://qiaoyihang.iteye.com/
- 大小: 152.1 KB
- 大小: 146.7 KB
- 大小: 152.4 KB
分享到:
相关推荐
Android应用通过与Red5服务器建立RTMP连接,将手机摄像头捕获的视频流推送到服务器,然后服务器再将这些流分发给观众。 Red5服务器是一个开源的流媒体服务器,支持RTMP、RTMPT、RTMPE、RTMPTE和RTMPS等多种协议。它...
《Android与Red5流媒体服务器连接的实现及JUV-RTMP-Client库的应用》 在移动应用开发中,尤其是在视频直播或者视频点播场景下,Android设备与流媒体服务器的交互是必不可少的一环。本篇文章将深入探讨如何利用...
Android客户端需要实现RTMP客户端功能,与Red5服务器建立连接,发送和接收数据。 4. **HLS协议**:虽然Red5支持RTMP,但为了适应移动设备和不同网络环境,系统可能还包含了HLS协议的支持。HLS是Apple提出的适应性流...
在这个案例中,Android应用负责采集设备的音频和视频数据,通过RTMP协议与Red5服务器建立连接,将数据推送到服务器。这涉及到的关键技术包括: 1. **多媒体数据采集**:使用Android的MediaRecorder或Camera API来...
4. **RTMP服务器选择**:RTMP服务器可以是Red5或FMS(Flash Media Server)。Red5是一个开源的流媒体服务器,支持RTMP、HLS等多种协议,适合开发者自建和定制。FMS是Adobe官方的商业产品,功能强大但需要购买授权,...
"Android JAVACV RTMP Client"项目就是为了解决这一问题,它利用了JavaCV库来实现音视频的录制,并通过RTMP协议将数据流传输到RED5服务器。以下将详细介绍其中涉及的关键知识点: 1. **Android音视频录制**:...
通过研究这些源代码,开发者可以深入理解如何将Red5与Android结合,构建完整的直播解决方案,包括如何初始化和配置Red5服务器,以及如何在Android应用中集成RTMP库进行直播和播放。 总的来说,构建一个Red5与...
Android应用通过与Red5服务器建立RTMP连接,可以实现实时的音视频数据传输。 三、Android音视频处理: 在Android应用中,需要利用MediaRecorder和MediaPlayer类来捕获、处理和播放音视频数据。MediaRecorder用于...
当Android客户端启动直播时,它会通过RTMP连接到Red5服务器,将摄像头捕获的视频流和音频流发送到服务器。Red5接收这些流并进行处理,如录制、存储或者转发给其他客户端。服务器端的直播流处理包括流接收、存储、...
1. **流媒体服务器**:Red5 Pro 作为一个流媒体服务器,能够处理视频和音频数据的传输,支持RTMP、HLS、RTSP等多种协议,为开发者提供了丰富的API和插件机制来扩展其功能。 2. **发布与播放**:用户可以通过Red5 ...
Red5是一款开源的Java流媒体服务器,用于提供实时流传输服务。它支持多种协议,如RTMP(Real-Time Messaging Protocol)、HLS(HTTP Live Streaming)和RTSP(Real-Time Streaming Protocol),广泛应用于在线直播、...
在Android平台上实现直播和视频点播功能,通常需要利用服务器端的流媒体处理技术,这里提到了Red5服务器。Red5是一款开源的流媒体服务器,它支持RTMP、HLS、RTSP等多种协议,适用于直播、点播以及录播等多种场景。在...
android的rtmp客户端库,经过修改,可以连上red5服务器,并收发音视频数据
在Android平台上,将录制的视频发送到Red5服务器是一个涉及多个技术栈的过程。Red5是一款开源的流媒体服务器,能够处理RTMP(Real-Time Messaging Protocol)协议的数据,常用于在线视频直播、点播等场景。以下我们...
Red5支持RTMP,而Android客户端通常使用这个协议从服务器获取直播流。 5. **HLS协议**:HTTP Live Streaming是一种适应性流媒体协议,适用于移动设备和低带宽环境。虽然Red5本身不直接支持HLS,但可以通过插件或...
该压缩包文件“Android应用源码之Red5+Android 直播系统的架构服务端的直播流工程.zip”涉及的是一个完整的Android直播系统架构,其中包括了服务端和客户端的源码。这个系统基于Red5服务器,这是一个开源的流媒体...
- 在Android平台上,我们可以使用Android SDK中的MediaRecorder类来捕获设备的音频和视频,然后通过RTMP协议推送到Red5服务器。 - 观看直播则可以通过VLC等库或者自建的播放器,使用HLS或RTMP协议从Red5服务器拉取...
-将android手机模拟为监控摄像头,推送视频流至RTMP服务器。 -不使用flash,APP工作时,本机也无需安装flash。 -兼容大部分手机,一般2.3.3以上,ARM V7架构即可。 -默认分辨率352x288,特定场合下,640x480也能...
开发者可能需要理解如何配置Red5服务器,设置RTMP推流和拉流,以及如何与Android客户端进行交互。Red5提供了API和Web控制台,可以用来管理直播频道、存储和检索流媒体内容。服务端的直播流工程可能涉及到以下几个...
4. **Java RTMP客户端库**:由于Android原生不支持RMPT,我们需要借助第三方库,如librtmp-java或EasyRtmpClient,这些库实现了RTMP协议,使得Android应用能够与Red5服务器通信。Java代码通常会创建一个RTMP连接,...