IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android之音频和视频的提取 -> 正文阅读

[移动开发]Android之音频和视频的提取

Android之音频和视频的提取

权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

private boolean checkPermission() {
	return ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
	if (requestCode == 101 && grantResults.length > 0) {
		if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
			showShortToast("权限申请成功");
		} else {
			showShortToast("权限申请拒绝");
		}
	}
}

将视频音频分离开

将视频和音频分离开

private void splitMediaToVideoAndRadio(){
	// 视频提取器
	MediaExtractor extractor = new MediaExtractor();
	try {
		extractor.setDataSource(getFileDirPath()+File.separator + "source_demo.mp4");
	} catch (IOException e) {
		e.printStackTrace();
		showShortToast("视频资源路径出错");
	}
	// 获取通道数
	int trackCount = extractor.getTrackCount();
	// 视频轨道索引
	int videoTrackIndex = 0;
	// 视频格式
	MediaFormat videoMediaFormat = null;
	// 音频轨道索引
	int audioTrackIndex = 0;
	// 音频格式
	MediaFormat audioMediaFormat = null;
	// 查找需要的视频轨道与音频轨道index
	for (int i = 0; i < trackCount; i++) { //遍历所以轨道
		MediaFormat itemMediaFormat = extractor.getTrackFormat(i);
		String itemMime = itemMediaFormat.getString(MediaFormat.KEY_MIME);
		if (itemMime.startsWith("video")) { //获取视频轨道位置
			videoTrackIndex = i;
			videoMediaFormat = itemMediaFormat;
			Log.d(TAG,"video format start --- ");
			Log.d(TAG,"video format --> \r\n"+itemMediaFormat.toString());
			Log.d(TAG,"video format end --- ");

		}else if (itemMime.startsWith("audio")) { //获取音频轨道位置
			audioTrackIndex = i;
			audioMediaFormat = itemMediaFormat;
			Log.d(TAG,"audio format start --- ");
			Log.d(TAG,"audio format --> \r\n"+itemMediaFormat.toString());
			Log.d(TAG,"audio format end --- ");
		}
	}
	File outVideoFile = new File(getFileOutPath() + File.separator + "video.h264");
	File outRadioFile = new File(getFileOutPath() + File.separator + "audio.acc");

	if(outVideoFile.exists()){
		outVideoFile.delete();
	}

	if(outRadioFile.exists()){
		outRadioFile.delete();
	}

	try{
		FileOutputStream videoOutputStream = new FileOutputStream(outVideoFile);
		FileOutputStream radioOutputStream = new FileOutputStream(outRadioFile);

		// 分离视频

		// 获取视频输出缓存的最大大小
		int maxVideoBufferCount = videoMediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
		ByteBuffer videoByteBuffer = ByteBuffer.allocate(maxVideoBufferCount);
		extractor.selectTrack(videoTrackIndex);
		int length;
		while ((length = extractor.readSampleData(videoByteBuffer,0)) != -1){
			byte [] bytes = new byte[length];
			// 获取字节
			videoByteBuffer.get(bytes);
			// 写入字节
			videoOutputStream.write(bytes);
			videoByteBuffer.clear();
			// 预先加载后面的数据
			extractor.advance();
		}
		videoOutputStream.flush();
		videoOutputStream.close();
		extractor.unselectTrack(videoTrackIndex);

		// 分离音频
		int maxAudioBufferCount = audioMediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);//获取音频的输出缓存的最大大小
		ByteBuffer audioByteBuffer = ByteBuffer.allocate(maxAudioBufferCount);
		extractor.selectTrack(audioTrackIndex);//选择音频轨道
		while ((length = extractor.readSampleData(audioByteBuffer, 0)) != -1) {
			byte[] bytes = new byte[length];
			audioByteBuffer.get(bytes);

			// 添加adts头
			byte[] adtsData = new byte[length + 7];
			addADTStoPacket(adtsData, length+7);
			System.arraycopy(bytes, 0, adtsData, 7, length);

			radioOutputStream.write(bytes);
			audioByteBuffer.clear();
			extractor.advance();
		}

		radioOutputStream.flush();
		radioOutputStream.close();


		showShortToast("分离音频视频成功");
	}catch (Exception e){
		e.printStackTrace();
		showShortToast("分离音频视频失败");
	}
}

private static void addADTStoPacket(byte[] packet, int packetLen) {
	/*
	标识使用AAC级别 当前选择的是LC
	一共有1: AAC Main 2:AAC LC (Low Complexity) 3:AAC SSR (Scalable Sample Rate) 4:AAC LTP (Long Term Prediction)
	*/
	int profile = 2;
	int frequencyIndex = 0x04; //设置采样率
	int channelConfiguration = 2; //设置频道,其实就是声道

	// fill in ADTS data
	packet[0] = (byte) 0xFF;
	packet[1] = (byte) 0xF9;
	packet[2] = (byte) (((profile - 1) << 6) + (frequencyIndex << 2) + (channelConfiguration >> 2));
	packet[3] = (byte) (((channelConfiguration & 3) << 6) + (packetLen >> 11));
	packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
	packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
	packet[6] = (byte) 0xFC;
}

将视频分离成无声视频和音频

视频

private void generateMediaVideo(){
	// 视频提取器
	MediaExtractor extractor = new MediaExtractor();
	try {
		extractor.setDataSource(getFileDirPath()+File.separator + "source_demo.mp4");
	} catch (IOException e) {
		e.printStackTrace();
		showShortToast("视频资源路径出错");
	}
	// 获取通道数
	int trackCount = extractor.getTrackCount();
	// 视频轨道索引
	int videoTrackIndex = 0;
	// 视频格式
	MediaFormat videoMediaFormat = null;

	// 查找需要的视频轨道与音频轨道index
	for (int i = 0; i < trackCount; i++) { //遍历所以轨道
		MediaFormat itemMediaFormat = extractor.getTrackFormat(i);
		String itemMime = itemMediaFormat.getString(MediaFormat.KEY_MIME);
		if (itemMime.startsWith("video")) { //获取视频轨道位置
			videoTrackIndex = i;
			videoMediaFormat = itemMediaFormat;
			Log.d(TAG,"video format start --- ");
			Log.d(TAG,"video format --> \r\n"+itemMediaFormat.toString());
			Log.d(TAG,"video format end --- ");

		}
	}

	File outVideoFile = new File(getFileOutPath() + File.separator + "out_video.mp4");
	if(outVideoFile.exists()){
		outVideoFile.delete();
	}

	try{
		// 分离视频
		MediaMuxer mediaMuxer = new MediaMuxer(outVideoFile.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
		int mVideoTrackIndex  = mediaMuxer.addTrack(videoMediaFormat);
		mediaMuxer.start();
		MediaCodec.BufferInfo info =  new MediaCodec.BufferInfo();
		info.presentationTimeUs =  0;

		extractor.selectTrack(videoTrackIndex);
		int videoFlag = extractor.getSampleFlags();
		long videoFrameRate = 1000 * 1000 /(videoMediaFormat.getInteger(MediaFormat.KEY_FRAME_RATE));
		 int length;
		ByteBuffer buffer = ByteBuffer.allocate(100 * 1024);
		while ((length = extractor.readSampleData(buffer,0)) != -1){
			info.offset = 0;
			info.size = length;
			info.flags = videoFlag;
			info.presentationTimeUs += videoFrameRate;
			mediaMuxer.writeSampleData(mVideoTrackIndex, buffer, info);
			// 预先加载后面的数据
			extractor.advance();
		}

		extractor.release();
		mediaMuxer.stop();
		mediaMuxer.release();

		showShortToast("生成视频文件成功");
	}catch (Exception e){
		e.printStackTrace();
		showShortToast("视频生成失败");
	}
}

音频

private void generateMediaRadio(){
	// 视频提取器
	MediaExtractor extractor = new MediaExtractor();
	try {
		extractor.setDataSource(getFileDirPath()+File.separator + "source_demo.mp4");
	} catch (IOException e) {
		e.printStackTrace();
		showShortToast("视频资源路径出错");
	}
	// 获取通道数
	int trackCount = extractor.getTrackCount();
	// 视频轨道索引
	int radioTrackIndex = 0;
	// 视频格式
	MediaFormat radioMediaFormat = null;
	long radioFrameRate = 0;

	// 查找需要的视频轨道与音频轨道index
	for (int i = 0; i < trackCount; i++) { //遍历所以轨道
		MediaFormat itemMediaFormat = extractor.getTrackFormat(i);
		String itemMime = itemMediaFormat.getString(MediaFormat.KEY_MIME);
		if (itemMime.startsWith("audio")) { //获取音频轨道位置
			radioTrackIndex = i;
			radioMediaFormat = itemMediaFormat;
			Log.d(TAG,"audio format start --- ");
			Log.d(TAG,"audio format --> \r\n"+itemMediaFormat.toString());
			Log.d(TAG,"audio format end --- ");

			extractor.selectTrack(i);
			long first_sampletime = extractor.getSampleTime();
			extractor.advance();
			long second_sampletime = extractor.getSampleTime();
			radioFrameRate = Math.abs(second_sampletime - first_sampletime);//时间戳
			extractor.unselectTrack(i);

		}
	}

	File outVideoFile = new File(getFileOutPath() + File.separator + "out_audio.mp4");
	if(outVideoFile.exists()){
		outVideoFile.delete();
	}

	try{
		// 分离音频
		MediaMuxer mediaMuxer = new MediaMuxer(outVideoFile.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
		int mVideoTrackIndex  = mediaMuxer.addTrack(radioMediaFormat);
		mediaMuxer.start();
		MediaCodec.BufferInfo info =  new MediaCodec.BufferInfo();
		info.presentationTimeUs =  0;

		extractor.selectTrack(radioTrackIndex);
		int videoFlag = extractor.getSampleFlags();
		int length;
		ByteBuffer buffer = ByteBuffer.allocate(100 * 1024);
		while ((length = extractor.readSampleData(buffer,0)) != -1){
			info.offset = 0;
			info.size = length;
			info.flags = videoFlag;
			info.presentationTimeUs += radioFrameRate;
			mediaMuxer.writeSampleData(mVideoTrackIndex, buffer, info);
			// 预先加载后面的数据
			extractor.advance();
		}

		extractor.release();
		mediaMuxer.stop();
		mediaMuxer.release();

		showShortToast("音频生成成功");
	}catch (Exception e){
		e.printStackTrace();
		showShortToast("音频生成失败");
	}
}
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-01 17:00:30  更:2021-10-01 17:01:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:03:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码