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("音频生成失败");
	}
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值