java代码视频数据和音频数据的采集
我们经常用直播,但是直播怎么做呢?前面的文章已经搭建好了推流服务器,现在就让我们先从采集数据开始吧,然后压缩数据,然后推流数据等等,一步步来,一定会成个大胖纸的。加油!
Activity.java
public class MainActivity extends Activity {static final String URL = "rtmp://112.74.96.116/live/jason";private LivePusher live;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surface);//相机图像的预览live = new LivePusher(surfaceView.getHolder());}/*** 开始直播* @param btn*/public void mStartLive(View view) {Button btn = (Button)view;if(btn.getText().equals("开始直播")){live.startPush(URL);btn.setText("停止直播");}else{live.stopPush();btn.setText("开始直播");}}/*** 切换摄像头* @param btn*/public void mSwitchCamera(View btn) {live.switchCamera();}}
Push业务
定义接口Pusher.java
public abstract class Pusher {public abstract void startPush();public abstract void stopPush();public abstract void release();
}
视频Push
VideoPusher.java
public class VideoPusher extends Pusher implements Callback, PreviewCallback{private SurfaceHolder surfaceHolder;private Camera mCamera;private VideoParam videoParams;private byte[] buffers;private boolean isPushing = false;private PushNative pushNative;public VideoPusher(SurfaceHolder surfaceHolder, VideoParam videoParams, PushNative pushNative) {this.surfaceHolder = surfaceHolder;this.videoParams = videoParams;this.pushNative = pushNative;surfaceHolder.addCallback(this);}@Overridepublic void startPush() {isPushing = true;}@Overridepublic void stopPush() {isPushing = false;}@Overridepublic void surfaceCreated(SurfaceHolder holder) {startPreview();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {}@Overridepublic void release() {stopPreview();}/*** 切换摄像头*/public void switchCamera() {if(videoParams.getCameraId() == CameraInfo.CAMERA_FACING_BACK){videoParams.setCameraId(CameraInfo.CAMERA_FACING_FRONT);}else{videoParams.setCameraId(CameraInfo.CAMERA_FACING_BACK);}//重新预览stopPreview();startPreview();}/*** 开始预览*/private void startPreview() {try {//SurfaceView初始化完成,开始相机预览mCamera = Camera.open(videoParams.getCameraId());mCamera.setPreviewDisplay(surfaceHolder);//获取预览图像数据buffers = new byte[videoParams.getWidth() * videoParams.getHeight() * 4];mCamera.addCallbackBuffer(buffers);mCamera.setPreviewCallbackWithBuffer(this);mCamera.startPreview();} catch (IOException e) {e.printStackTrace();}}/*** 停止预览*/private void stopPreview() {if(mCamera != null){ mCamera.stopPreview();mCamera.release();mCamera = null;}}@Overridepublic void onPreviewFrame(byte[] data, Camera camera) {if(mCamera != null){mCamera.addCallbackBuffer(buffers);}if(isPushing){//回调函数中获取图像数据,然后给Native代码编码pushNative.fireVideo(data);}}
}
音频AudioPusher.java
public class AudioPusher extends Pusher{private AudioParam audioParam;private AudioRecord audioRecord;private boolean isPushing = false;private int minBufferSize;private PushNative pushNative;public AudioPusher(AudioParam audioParam, PushNative pushNative) {this.audioParam = audioParam;this.pushNative = pushNative;int channelConfig = audioParam.getChannel() == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO; //最小缓冲区大小minBufferSize = AudioRecord.getMinBufferSize(audioParam.getSampleRateInHz(), channelConfig, AudioFormat.ENCODING_PCM_16BIT);audioRecord = new AudioRecord(AudioSource.MIC, audioParam.getSampleRateInHz(), channelConfig, AudioFormat.ENCODING_PCM_16BIT, minBufferSize);}@Overridepublic void startPush() {isPushing = true;//启动一个录音子线程new Thread(new AudioRecordTask()).start();}@Overridepublic void stopPush() {isPushing = false;audioRecord.stop();}@Overridepublic void release() {if(audioRecord != null){audioRecord.release();audioRecord = null;}}class AudioRecordTask implements Runnable{@Overridepublic void run() {//开始录音audioRecord.startRecording();while(isPushing){//通过AudioRecord不断读取音频数据byte[] buffer = new byte[minBufferSize];int len = audioRecord.read(buffer, 0, buffer.length);if(len > 0){//传给Native代码,进行音频编码pushNative.fireAudio(buffer, len);}}}}
}
push总类,音频视频同时push
public class LivePusher implements Callback {private SurfaceHolder surfaceHolder;private VideoPusher videoPusher;private AudioPusher audioPusher;private PushNative pushNative;public LivePusher(SurfaceHolder surfaceHolder) {this.surfaceHolder = surfaceHolder;surfaceHolder.addCallback(this);prepare();}/*** 预览准备*/private void prepare() {pushNative = new PushNative();//实例化视频推流器VideoParam videoParam = new VideoParam(480, 320, CameraInfo.CAMERA_FACING_BACK);videoPusher = new VideoPusher(surfaceHolder,videoParam,pushNative);//实例化音频推流器AudioParam audioParam = new AudioParam();audioPusher = new AudioPusher(audioParam,pushNative);}/*** 切换摄像头*/public void switchCamera() {videoPusher.switchCamera();}/*** 开始推流*/public void startPush(String url) {videoPusher.startPush();audioPusher.startPush();pushNative.startPush(url);}/*** 停止推流*/public void stopPush() {videoPusher.stopPush();audioPusher.stopPush();pushNative.stopPush();}/*** 释放资源*/private void release() {videoPusher.release();audioPusher.release();pushNative.release();}@Overridepublic void surfaceCreated(SurfaceHolder holder) {}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {stopPush();release();}
}
参数的设置:
public class LivePusher implements Callback {private SurfaceHolder surfaceHolder;private VideoPusher videoPusher;private AudioPusher audioPusher;private PushNative pushNative;public LivePusher(SurfaceHolder surfaceHolder) {this.surfaceHolder = surfaceHolder;surfaceHolder.addCallback(this);prepare();}/*** 预览准备*/private void prepare() {pushNative = new PushNative();//实例化视频推流器VideoParam videoParam = new VideoParam(480, 320, CameraInfo.CAMERA_FACING_BACK);videoPusher = new VideoPusher(surfaceHolder,videoParam,pushNative);//实例化音频推流器AudioParam audioParam = new AudioParam();audioPusher = new AudioPusher(audioParam,pushNative);}/*** 切换摄像头*/public void switchCamera() {videoPusher.switchCamera();}/*** 开始推流*/public void startPush(String url) {videoPusher.startPush();audioPusher.startPush();pushNative.startPush(url);}/*** 停止推流*/public void stopPush() {videoPusher.stopPush();audioPusher.stopPush();pushNative.stopPush();}/*** 释放资源*/private void release() {videoPusher.release();audioPusher.release();pushNative.release();}@Overridepublic void surfaceCreated(SurfaceHolder holder) {}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {stopPush();release();}}
package com.dongnaoedu.live.params;/*** 视频数据参数*/
public class VideoParam {private int width;private int height;private int cameraId;public VideoParam(int width, int height, int cameraId) {super();this.width = width;this.height = height;this.cameraId = cameraId;}public int getWidth() {return width;}public void setWidth(int width) {this.width = width;}public int getHeight() {return height;}public void setHeight(int height) {this.height = height;}public int getCameraId() {return cameraId;}public void setCameraId(int cameraId) {this.cameraId = cameraId;}}
当然数据有了,我们必须通过C++代码完成操作,所以如下:
/*** 调用C代码进行编码与推流*/
public class PushNative {public native void startPush(String url);public native void stopPush();public native void release();/*** 设置视频参数* @param width* @param height* @param bitrate* @param fps*/public native void setVideoOptions(int width, int height, int bitrate, int fps);/*** 设置音频参数* @param sampleRateInHz* @param channel*/public native void setAudioOptions(int sampleRateInHz, int channel);/*** 发送视频数据* @param data*/public native void fireVideo(byte[] data);/*** 发送音频数据* @param data* @param len*/public native void fireAudio(byte[] data, int len);static{System.loadLibrary("dn_live");}
}
上面是第一节操作,我们后面的文章将慢慢介绍C++的实现,牵扯到jni的使用,可能会单独有一篇文章进行介绍,小朋友记得加关注哦。
java代码视频数据和音频数据的采集相关推荐
- Java提取视频中的音频
话不多说,上代码 Scanner scanner = new Scanner(System.in);System.out.println("请输入被提取音频的视频:");Strin ...
- Java Mp3转化WAV/PCM音频数据,解码详细解析,提取每一帧数据集合/比特流/播放,一行代码!
导言 大家好!我是原子君 1.因为Java本身只支持,wav,缺少mp3的解码器,所以Java自带的无法对mp3进行处理,这种MPEG-*音频有损压缩标准编码,更不要说使用Java的音频格式和音频流就 ...
- python音频 降噪_从视频中提取音频数据,然后应用傅里叶对音频降噪(python)...
视频准备 QQ有热键 然后随便打开一个视频网站进行录屏 我选择B站 从视频中提取音频 需要安装包moviepy pip install moviepy 提取代码 from moviepy.editor ...
- 从视频中提取音频数据,然后应用傅里叶对音频降噪(python)
视频准备 QQ有热键 然后随便打开一个视频网站进行录屏 我选择B站 从视频中提取音频 需要安装包moviepy pip install moviepy 提取代码 from moviepy.editor ...
- 解决POI事件驱动模式读取不到Java代码创建的Excel表格数据问题
场景 使用POI官网上的事件驱动模式的示例方法,读取单sheet单次创建的Excel表格文件(.xlsx),Microsoft Excel和WPS Excel创建的表格文件可以正常读取数据,但是jav ...
- java如何向数据库中插入数据_如何控制Java代码向数据库中插入数据
慕哥6287543 Java程序向数据库中插入数据,代码如下:123456789101112131415161718192021222324252627282930313233343536373839 ...
- MongoDB最简单的入门教程之三 使用Java代码往MongoDB里插入数据
前两篇教程我们介绍了如何搭建MongoDB的本地环境. 这篇教程我们会介绍如何使用Java代码来连接MongoDB. 如果您是基于Maven进行依赖管理的Java项目,只需要在您的pom.xml里加入 ...
- 使用FFMPEG库封装264视频和acc音频数据到MP4文件中
准备 ffmepeg 4.4 一段H264的视频文件 一段acc格式的音频文件 封装流程 1.使用avformat_open_input分别打开视频和音频文件,初始化其AVFormatContext, ...
- 笨鸟先飞java代码,笨鸟先飞之Java--MySql中文数据乱码为哪般???
图一:在drp的分销商模块,每次修改区域虽然返回修改成功,但是每次读取到的中文数据都是"???"的字符串,但数字和字母的数据却不受影响. 图二:不管是drp还是hibernate项 ...
最新文章
- java static 作用详解
- 回顾2020,我国无人机经历了四大新变化
- Blocking/Non-Blocking VS Sync/Async VS Overlapped
- matlab mandrill,MATLAB】MATLAB的自带数据及可生成数据的函数
- js中执行到一个if就停止的代码_Node 中如何引入一个模块及其细节
- CSS3的边框(二)
- OBS鉴权实现的宝典秘籍,速拿!
- 微博:坚决打击在政务、媒体官微下刷量控评的行为
- kcf算法中cos_window是什么意思_知网/维普查重系统算法介绍(史上最详细)
- 强化学习 ---baselines项目之 Atari游戏的网络结构解析
- 微信小程序 人脸识别登陆模块
- mac系统修改idea运行内存
- java 中subtract_Java.math.BigDecimal.subtract()方法实例详解
- 赛格威航空T15评测骑行测试
- c语言三角分解法解方程,用直接三角分解法解线性方程组.ppt
- 2020诺贝尔文学奖得主,死亡的诗歌
- 中国人工智能大赛机器阅读理解任务冠军方案出炉~
- n2n内网穿透及代理服务
- Visual Studio 2017 设置语言以及下载语言包
- sbt 使用国内镜像 sbt 下载很慢 (尝试了几乎全网所有办法,依然无效。最后解决!!!)