Android之音频和视频的提取
权限
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 --> rn"+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 --> rn"+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) {
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 --> rn"+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 --> rn"+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("音频生成失败");
}
}