首页 > 编程语言 >音视频:JavaCV 采集摄像头和麦克风数据推送RTMP流

音视频:JavaCV 采集摄像头和麦克风数据推送RTMP流

时间:2022-12-31 09:56:05浏览次数:48  
标签:int 音视频 channels RTMP new JavaCV recorder FFmpegFrameRecorder sampleRate

需要进行简单的音视频编程,如果不是特别数据C/C++,那么JavaCV应该是比较好的选择,下面记录一下使用JavaCV采集桌面数据的方式。

同时采集视频和音频需要最好采用不同的线程进行。

1. 视频采集

视频采集使用OpenCVFrameGrabber(当然也可以使用FFmpegFrameGrabber):

public class VideoRecorder implements Runnable {

	private static final int VIDEO_DEVICE_INDEX = 0;
	private FFmpegFrameRecorder recorder;
	private int width, height;
	public VideoRecorder(FFmpegFrameRecorder recorder, int width, int height) {
		this.recorder = recorder;
		this.width = width;
		this.height = height;
	}

	@Override
	public void run() {
		try {
			OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(VIDEO_DEVICE_INDEX);
			grabber.setImageWidth(width);
			grabber.setImageHeight(height);
			grabber.start();
			
			long startTS = 0, videoTS = 0;
			Frame frame = null;
			while (!Thread.interrupted() && (frame = grabber.grab()) != null) {
				if (startTS == 0) {
					startTS = System.currentTimeMillis();
				}
				videoTS = 1000 * (System.currentTimeMillis() - startTS);
				if (videoTS > recorder.getTimestamp()) {
					recorder.setTimestamp(videoTS);
				}
				recorder.record(frame);
			}
			
			grabber.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

这里的recorder(FFmpegFrameRecorder)是推流使用的,即OpenCVFrameGrabber采集的视频流推送到recorder中,具体在下面的rtmp推流中说明。

2. 音频采集

音频采集直接采用Java的API,读取麦克风的数据:

public class AudioRecoder implements Runnable {

	private FFmpegFrameRecorder recorder;
	private int channels;
	private int sampleRate;
	public AudioRecoder(FFmpegFrameRecorder recorder, int sampleRate, int channels) {
		this.recorder = recorder;
		this.sampleRate = sampleRate;
		this.channels = channels;
	}

	@Override
	public void run() {
		try {
			AudioFormat format = new AudioFormat(Float.valueOf(sampleRate), 16, channels, true, false);
			TargetDataLine line = (TargetDataLine) AudioSystem.getLine(new DataLine.Info(TargetDataLine.class, format));
			line.open(format);
			line.start();

			int sampleRate = (int) format.getSampleRate();
			int numChannels = format.getChannels();
			byte[] buffer = new byte[sampleRate * numChannels];

			while (!Thread.interrupted()) {
				int nBytesRead = 0;
				while (nBytesRead == 0) {
					nBytesRead = line.read(buffer, 0, line.available());
				}
				int nSamplesRead = nBytesRead / 2;
				short[] samples = new short[nSamplesRead];
				ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(samples);
				ShortBuffer sBuff = ShortBuffer.wrap(samples, 0, nSamplesRead);
				recorder.recordSamples(sampleRate, numChannels, sBuff);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

需要注意的是,指定的位数是16,所以需要将采集的byte转化为short(小端模式),同样的,这里的recorder(FFmpegFrameRecorder)是推流使用的。

3. rtmp推流

rtmp推流采用FFmpegFrameRecorder,format设置为FLV,视频编码采用H264,音频编码采用AAC。

public class Recoder {

	
	public static void main(String[] args) throws Exception {
		String rtmpURI = "rtmp://127.0.0.1:1935/app/test";
		int width = 1280, height = 720, sampleRate = 44100, channels = 2;
		FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtmpURI, width, height, channels);
		// Video
		recorder.setInterleaved(true);
		recorder.setVideoOption("tune", "zerolatency");
		recorder.setVideoOption("preset", "ultrafast");
		recorder.setVideoOption("crf", "28");
		recorder.setVideoBitrate(2000000);
		// H.264
		recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
		recorder.setFormat("flv");
		recorder.setFrameRate(25);
		recorder.setGopSize(25 * 2);
		// Audio
		recorder.setAudioOption("crf", "0");
		recorder.setAudioQuality(0);
		recorder.setAudioBitrate(192000);
		recorder.setSampleRate(sampleRate);
		recorder.setAudioChannels(channels);
		// AAC
		recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
		
		recorder.start();
		Thread vt = new Thread(new VideoRecorder(recorder, width, height));
		Thread at = new Thread(new AudioRecoder(recorder, sampleRate, channels));
		
		vt.start();
		at.start();
		
		vt.join();
		at.join();
		
		recorder.close();
	}
}

这里需要注意的是,启动音视频采集线程后,需要将线程加入到主线程中:

vt.join();
at.join()

4. 效果预览

可以使用VLC拉流查看recorder的推流效果:

注意rtmp服务器需要自己搭建。

标签:int,音视频,channels,RTMP,new,JavaCV,recorder,FFmpegFrameRecorder,sampleRate
From: https://www.cnblogs.com/michong2022/p/17016242.html

相关文章

  • 音视频:JavaCV 采集桌面画面并显示的方法
    需要进行简单的音视频编程,如果不是特别数据C/C++,那么JavaCV应该是比较好的选择,下面记录一下使用JavaCV采集桌面数据的方式。使用FFmpegFrameGrabber采集桌面数据,指定输入......
  • 音视频:JavaCV 两种摄像头视频数据采集的方法
    需要进行简单的音视频编程,如果不是特别数据C/C++,那么JavaCV应该是比较好的选择,下面记录一下使用JavaCV采集摄像头的两头方式。1.OpenCV使用OpenCVFrameGrabber采集指定......
  • 乐影音下载器(视频下载器) 英酷词典 音视频下载Chrome插件 必应好壁纸(必应壁纸)
    乐影音下载器(视频下载器)官方主页-iMath-博客园(cnblogs.com)英酷词典官方主页-iMath-博客园(cnblogs.com)音视频下载Chrome插件官方主页-iMath-博客园......
  • 【技术分享】如何实现功能完备性能优异的RTMP、RTSP播放器?
     技术背景这几年,我们对接了太多有RTSP或RTMP直播播放器诉求的开发者,他们当中除了寻求完整的解决方案的,还有些是技术探讨,希望能借鉴我们播放端的开发思路或功能特性,完善自己......
  • 音视频中的语音信号处理技术
    随着人工智能浪潮的到来,语音行业进入飞速发展时期,各大企业都在高薪寻觅从事语音技术的专业人才。作为语音行业中的音视频开发,越来越多的从业者开始接触和学习语音信号处理技......
  • 如何抓住社交风口下的音视频直播技术
    美国社交媒体巨头Facebook在4月发布了一系列以“音频社交”为核心的新产品。对于“久经沙场”的头号玩家,灵敏的商业嗅觉告诉他们,无论此时答案如何,快速跟进就对了。有人总......
  • 快速入门音视频技术的方法,有吗?
    最近有读者留言,说“想转行音视频开发,怎么做”,正巧,前几天我还在某乎上,看到有人在问音视频的学习资料,还是个大一的学生。 想说一句:真有眼光。 如今这个时代,想赚钱,一个共识是......
  • 直播预告 | 全场景音视频技术解析
    近年来,得益于移动互联网的普及和智能终端设备的广泛应用,短视频、直播、在线教育等各类形式的音视频业务场景风靡大众。但随着音视频应用越来越广泛,用户对于音视频服务的质量......
  • 音视频中的语音信号处理都包括哪些方向?
    随着人工智能浪潮的到来,语音行业进入飞速发展时期,各大企业都在高薪寻觅从事语音技术的专业人才。然而,语音信号处理包括语音增强、回声消除、麦克风阵列信号处理等多个研究方......
  • nginx搭建rtmp协议流媒体服务器总结
    最近在ubuntu12.04上搭建了一个rtmp服务器,感觉还挺麻烦的,所以记录下。大部分都是参考网络上的资料。前提:在linux下某个目录中新建一个nginx目录。然后进入该目录去下......