Skip to content

Commit ebe6023

Browse files
committed
update ffmpeg code
1 parent f001c52 commit ebe6023

File tree

8 files changed

+230
-10
lines changed

8 files changed

+230
-10
lines changed

.idea/caches/build_file_checksums.ser

-47 Bytes
Binary file not shown.

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
<activity android:name=".blocks.others.changeHue.ChangeHueActivity" />
5353
<activity android:name=".blocks.others.OthersActivity" />
5454
<activity android:name=".blocks.others.audioStyle.AudioStyleActivity" />
55+
<activity android:name=".blocks.ffmpeg.FFmpegActivity" />
56+
5557
<activity android:name=".whole.createVideoByVoice.CreateVideoByAudioDbActivity">
5658
<intent-filter>
5759
<action android:name="android.intent.action.MAIN" />

app/src/main/java/com/aserbao/androidcustomcamera/base/activity/BaseActivity.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public void onCreate(Bundle savedInstanceState) {
2828
ButterKnife.bind(this);
2929
startRequestPermission();
3030
initView();
31-
getLifecycle()
3231
}
3332

3433
private void startRequestPermission() {

app/src/main/java/com/aserbao/androidcustomcamera/blocks/ffmpeg/FFmpegActivity.kt

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package com.aserbao.androidcustomcamera.blocks.ffmpeg
33
import Jni.FFmpegCmd
44
import VideoHandle.*
55
import android.os.Environment
6+
import android.support.annotation.MainThread
67
import android.util.Log
78
import android.view.View
9+
import android.widget.Toast
810
import com.aserbao.androidcustomcamera.base.activity.RVBaseActivity
911
import com.aserbao.androidcustomcamera.base.beans.BaseRecyclerBean
1012
import com.aserbao.androidcustomcamera.blocks.ffmpeg.beans.WaterFilter
@@ -18,12 +20,13 @@ var absolutePath = Environment.getExternalStorageDirectory().absolutePath
1820
class FFmpegActivity : RVBaseActivity(),OnEditorListener {
1921

2022
override fun initGetData() {
23+
mBaseRecyclerBeen.add(BaseRecyclerBean("取消", 100))
2124
mBaseRecyclerBeen.add(BaseRecyclerBean("视频中抽取音频", 0))
2225
mBaseRecyclerBeen.add(BaseRecyclerBean("视频添加水印", 1))
2326
mBaseRecyclerBeen.add(BaseRecyclerBean("无损视频合并", 2))
2427
mBaseRecyclerBeen.add(BaseRecyclerBean("多段视频合并", 3))
2528
mBaseRecyclerBeen.add(BaseRecyclerBean("多段视频加水印并合成", 4))
26-
mBaseRecyclerBeen.add(BaseRecyclerBean("取消", 5))
29+
mBaseRecyclerBeen.add(BaseRecyclerBean("视频添加配乐并调整音量大小", 5))
2730

2831
mInputs.add(WaterFilter(videoPath1,png1))
2932
mInputs.add(WaterFilter(videoPath2,png2))
@@ -53,12 +56,19 @@ class FFmpegActivity : RVBaseActivity(),OnEditorListener {
5356
override fun itemClickBack(view: View, position: Int, isLongClick: Boolean, comeFrom: Int) {
5457
mStartTime = System.currentTimeMillis()
5558
when(position){
59+
100 ->{
60+
// FFmpegCmd.exit()
61+
addMusicToVideo1()
62+
}
5663
0 ->{
5764
FFmpegUtils.demuxer(videoPath1,outputMusicPath,EpEditor.Format.MP3,this)
5865
}
5966
1 ->{
60-
var epVideo1 = EpVideo(videoPath1)
61-
epVideo1.addDraw(EpDraw(png1,0,0,576f,1024f,false))
67+
var tempVideoPath = "/storage/emulated/0/Android/data/com.getremark.playground/files/Movies/15871817738614870009935443.mp4"
68+
var tempBitmapPath = "/storage/emulated/0/playground/temp/123.png"
69+
var epVideo1 = EpVideo(tempVideoPath)
70+
// var epVideo1 = EpVideo(videoPath1)
71+
epVideo1.addDraw(EpDraw(tempBitmapPath,0,0,576f,1024f,false))
6272
val outputOption = EpEditor.OutputOption(outputPathMp4)
6373
EpEditor.exec(epVideo1, outputOption,this)
6474
}
@@ -83,11 +93,35 @@ class FFmpegActivity : RVBaseActivity(),OnEditorListener {
8393
addWaterFilterOneLine()
8494
}
8595
5 ->{
86-
FFmpegCmd.exit()
96+
addMusicToVideo()
8797
}
8898
}
8999
}
90100

101+
fun addMusicToVideo(){
102+
var inputVideo = absolutePath + "/5.mp4"
103+
// var inputVideo = absolutePath + "/temp.mp4"
104+
var inputMusic = absolutePath + "/input.mp3"
105+
var outputVideo = absolutePath + "/output.mp4"
106+
var videoVolume = 0.5f
107+
var musicVolume = 1f
108+
FFmpegUtils.music(inputVideo,inputVideo,outputVideo,videoVolume,musicVolume,this)
109+
// FFmpegUtils.addMusicForMp4(inputVideo,inputMusic,videoVolume,musicVolume,outputVideo,this)
110+
}
111+
fun addMusicToVideo1(){
112+
// var inputVideo = absolutePath + "/5.mp4"
113+
// var inputVideo = absolutePath + "/temp.mp4"
114+
// var inputMusic = absolutePath + "/input.mp3"
115+
// var inputVideo = "/storage/emulated/0/playground/temp/.capture/.remark-1588920936552.mp4"
116+
var inputVideo = absolutePath + "/test1.mp4"
117+
var inputMusic = absolutePath +"/er.m4a"
118+
var outputVideo = absolutePath + "/output.mp4"
119+
var videoVolume = 1f
120+
var musicVolume = 1f
121+
FFmpegUtils.music(inputVideo,inputMusic,outputVideo,videoVolume,musicVolume,this)
122+
}
123+
124+
91125
private fun addWaterFilterOneLine() {
92126
// ffmpeg -i 2.mp4 -i 3.mp4 -i img1.png -i img2.png -filter_complex "[0:v][2:v]overlay=0:0[in1];[1:v][3:v]overlay=0:10[in2];[in1][in2]concat" -y output.mp4
93127
//开始处理
@@ -160,6 +194,7 @@ class FFmpegActivity : RVBaseActivity(),OnEditorListener {
160194
if(cuurIndex == 3){
161195
itemClickBack(mBaseRv,2,false,2)
162196
}*/
197+
163198
Log.e(TAG, ": onSuccess 耗时: " + (System.currentTimeMillis() - mStartTime) );
164199
}
165200

@@ -170,6 +205,4 @@ class FFmpegActivity : RVBaseActivity(),OnEditorListener {
170205
override fun onProgress(progress: Float) {
171206
Log.e(TAG, ": onProgress" + progress );
172207
}
173-
174-
175208
}

app/src/main/java/com/aserbao/androidcustomcamera/blocks/ffmpeg/utils/FFmpegUtils.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,35 @@ public static void music(String videoin, String audioin, String output, float vi
7373
execCmd(cmd, d, onEditorListener);
7474
}
7575

76+
/**
77+
* 给视频添加配乐
78+
* @param inputVideoPath
79+
* @param inputMusicPath
80+
* @param videoVolume 0~1
81+
* @param musicVolume 0~1
82+
* @param outputVideoPath
83+
*/
84+
public static void addMusicForMp4(String inputVideoPath,String inputMusicPath,float videoVolume,float musicVolume,String outputVideoPath,final OnEditorListener onEditorListener){
85+
// ffmpeg -y -i 123.mp4 -i 5.aac -filter_complex "[0:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,volume=1.0[a0];
86+
// [1:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,volume=0.5[a1];[a0][a1]amix=inputs=2:duration=first[aout]" -map "[aout]" -ac 2 -c:v copy -map 0:v:0 output.mp4
87+
CmdList cmd = new CmdList();
88+
cmd.append("ffmpeg").append("-y").append("-i").append(inputVideoPath)
89+
.append("-i").append(inputMusicPath)
90+
.append("-filter_complex")
91+
.append("[0:a]volume=" + videoVolume + "[a0];[1:a]volume=" + musicVolume + "[a1];[a0][a1]amix=inputs=2:duration=first[aout]")
92+
.append("-map")
93+
.append("[aout]")
94+
.append("-ac")
95+
.append("2")
96+
/*.append("-c:v")
97+
.append("-copy")*/
98+
.append("-map")
99+
.append("0:v:0")
100+
.append(outputVideoPath);
101+
long d = VideoUitls.getDuration(inputVideoPath);
102+
execCmd(cmd, d, onEditorListener);
103+
}
104+
76105
/**
77106
* 音视频分离
78107
*
@@ -398,4 +427,6 @@ public void onProgress(final float progress) {
398427
}
399428
});
400429
}
430+
431+
401432
}

app/src/main/java/com/aserbao/androidcustomcamera/blocks/mediaExtractor/MediaExtractorActivity.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.aserbao.androidcustomcamera.base.interfaces.IDetailCallBackListener;
1313
import com.aserbao.androidcustomcamera.blocks.interfaces.ICallBackListener;
1414
import com.aserbao.androidcustomcamera.blocks.mediaExtractor.combineTwoVideo.CombineTwoVideos;
15+
import com.aserbao.androidcustomcamera.blocks.mediaExtractor.combineTwoVideo.CombineVideoAndMusic;
1516
import com.aserbao.androidcustomcamera.blocks.mediaExtractor.primary.FrequencyView;
1617
import com.aserbao.androidcustomcamera.blocks.mediaExtractor.primary.TransAacHandlerPure;
1718
import com.aserbao.androidcustomcamera.blocks.mediaExtractor.primary.decoder.DecoderAudioAAC2PCMPlay;
@@ -101,7 +102,11 @@ public void cuurentFrequenty(int cuurentFrequenty, double volume) {
101102
// decoderAudioAndGetDb.start(audioMp3Path1, MIMETYPE_AUDIO_MPEG);
102103
break;
103104
case R.id.exchange_video_and_audio:
104-
CombineTwoVideos.combineTwoVideos(path + "/aserbao.mp4", 0, path + "/lan.mp4", new File(path + "/aserbao.mp3"), this);
105+
// CombineTwoVideos.combineTwoVideos(path + "/aserbao.mp4", 0, path + "/lan.mp4", new File(path + "/aserbao.mp3"), this);
106+
String inputVideo = "/storage/emulated/0/douyin.mp4";
107+
String outputVideo = "/storage/emulated/0/douyinOut.mp4";
108+
String inputMusic = "/storage/emulated/0/pg/.bgm/40e613e5e3695ab44b4f31e25088d7ac";
109+
CombineVideoAndMusic.combineTwoVideos(inputMusic, 0, inputVideo, new File(outputVideo), this);
105110
break;
106111
case R.id.decoder_aac_and_player:
107112
String audioPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/aac.aac";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package com.aserbao.androidcustomcamera.blocks.mediaExtractor.combineTwoVideo;
2+
3+
import android.media.MediaCodec;
4+
import android.media.MediaExtractor;
5+
import android.media.MediaFormat;
6+
import android.media.MediaMuxer;
7+
import android.util.Log;
8+
9+
import com.aserbao.androidcustomcamera.base.interfaces.IDetailCallBackListener;
10+
11+
import java.io.File;
12+
import java.io.IOException;
13+
import java.nio.ByteBuffer;
14+
15+
/**
16+
* 功能: 替换视频1中的视频
17+
* @author aserbao
18+
* @date : On 2019/1/3 6:12 PM
19+
20+
* @project:AndroidCamera
21+
* @package:com.aserbao.androidcustomcamera.blocks.mediaCodec.primary.mp3TranslateAAC
22+
* @Copyright: 个人版权所有
23+
*/
24+
public class CombineVideoAndMusic {
25+
private static final String TAG = "CombineTwoVideos";
26+
/**
27+
* 合成视频1的音频和视频2的图像
28+
*
29+
* @param audioVideoPath 提供音频的视频
30+
* @param audioStartTime 音频的开始时间
31+
* @param frameVideoPath 提供图像的视频
32+
* @param combinedVideoOutFile 合成后的文件
33+
*/
34+
public static void combineTwoVideos(String audioVideoPath,
35+
long audioStartTime,
36+
String frameVideoPath,
37+
File combinedVideoOutFile,
38+
IDetailCallBackListener iDetailCallBackListener) {
39+
MediaExtractor audioVideoExtractor = new MediaExtractor();
40+
int mainAudioExtractorTrackIndex = -1; //提供音频的视频的音频轨(有点拗口)
41+
int mainAudioMuxerTrackIndex = -1; //合成后的视频的音频轨
42+
int mainAudioMaxInputSize = 0; //能获取的音频的最大值
43+
44+
MediaExtractor frameVideoExtractor = new MediaExtractor();
45+
int frameExtractorTrackIndex = -1; //视频轨
46+
int frameMuxerTrackIndex = -1; //合成后的视频的视频轨
47+
int frameMaxInputSize = 0; //能获取的视频的最大值
48+
int frameRate = 0; //视频的帧率
49+
long frameDuration = 0;
50+
51+
MediaMuxer muxer = null; //用于合成音频与视频
52+
53+
try {
54+
muxer = new MediaMuxer(combinedVideoOutFile.getPath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
55+
56+
audioVideoExtractor.setDataSource(audioVideoPath); //设置视频源
57+
//音轨信息
58+
int audioTrackCount = audioVideoExtractor.getTrackCount(); //获取数据源的轨道数
59+
//在此循环轨道数,目的是找到我们想要的音频轨
60+
for (int i = 0; i < audioTrackCount; i++) {
61+
MediaFormat format = audioVideoExtractor.getTrackFormat(i); //得到指定索引的记录格式
62+
String mimeType = format.getString(MediaFormat.KEY_MIME); //主要描述mime类型的媒体格式
63+
if (mimeType.startsWith("audio/")) { //找到音轨
64+
mainAudioExtractorTrackIndex = i;
65+
mainAudioMuxerTrackIndex = muxer.addTrack(format); //将音轨添加到MediaMuxer,并返回新的轨道
66+
mainAudioMaxInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE); //得到能获取的有关音频的最大值
67+
// mainAudioDuration = format.getLong(MediaFormat.KEY_DURATION);
68+
}
69+
}
70+
71+
//图像信息
72+
frameVideoExtractor.setDataSource(frameVideoPath); //设置视频源
73+
int trackCount = frameVideoExtractor.getTrackCount(); //获取数据源的轨道数
74+
//在此循环轨道数,目的是找到我们想要的视频轨
75+
for (int i = 0; i < trackCount; i++) {
76+
MediaFormat format = frameVideoExtractor.getTrackFormat(i); //得到指定索引的媒体格式
77+
String mimeType = format.getString(MediaFormat.KEY_MIME); //主要描述mime类型的媒体格式
78+
if (mimeType.startsWith("video/")) { //找到视频轨
79+
frameExtractorTrackIndex = i;
80+
frameMuxerTrackIndex = muxer.addTrack(format); //将视频轨添加到MediaMuxer,并返回新的轨道
81+
frameMaxInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE); //得到能获取的有关视频的最大值
82+
frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE); //获取视频的帧率
83+
frameDuration = format.getLong(MediaFormat.KEY_DURATION); //获取视频时长
84+
}
85+
}
86+
87+
muxer.start(); //开始合成
88+
89+
audioVideoExtractor.selectTrack(mainAudioExtractorTrackIndex); //将提供音频的视频选择到音轨上
90+
MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();
91+
ByteBuffer audioByteBuffer = ByteBuffer.allocate(mainAudioMaxInputSize);
92+
while (true) {
93+
int readSampleSize = audioVideoExtractor.readSampleData(audioByteBuffer, 0); //检索当前编码的样本并将其存储在字节缓冲区中
94+
if (readSampleSize < 0) { //如果没有可获取的样本则退出循环
95+
audioVideoExtractor.unselectTrack(mainAudioExtractorTrackIndex);
96+
break;
97+
}
98+
99+
long sampleTime = audioVideoExtractor.getSampleTime(); //获取当前展示样本的时间(单位毫秒)
100+
101+
if (sampleTime < audioStartTime) { //如果样本时间小于我们想要的开始时间就快进
102+
audioVideoExtractor.advance(); //推进到下一个样本,类似快进
103+
continue;
104+
}
105+
106+
if (sampleTime > audioStartTime + frameDuration) { //如果样本时间大于开始时间+视频时长,就退出循环
107+
break;
108+
}
109+
//设置样本编码信息
110+
audioBufferInfo.size = readSampleSize;
111+
audioBufferInfo.offset = 0;
112+
audioBufferInfo.flags = audioVideoExtractor.getSampleFlags();
113+
audioBufferInfo.presentationTimeUs = sampleTime - audioStartTime;
114+
115+
muxer.writeSampleData(mainAudioMuxerTrackIndex, audioByteBuffer, audioBufferInfo); //将样本写入
116+
audioVideoExtractor.advance(); //推进到下一个样本,类似快进
117+
}
118+
119+
frameVideoExtractor.selectTrack(frameExtractorTrackIndex); //将提供视频图像的视频选择到视频轨上
120+
MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
121+
ByteBuffer videoByteBuffer = ByteBuffer.allocate(frameMaxInputSize);
122+
while (true) {
123+
int readSampleSize = frameVideoExtractor.readSampleData(videoByteBuffer, 0); //检索当前编码的样本并将其存储在字节缓冲区中
124+
if (readSampleSize < 0) { //如果没有可获取的样本则退出循环
125+
frameVideoExtractor.unselectTrack(frameExtractorTrackIndex);
126+
break;
127+
}
128+
//设置样本编码信息
129+
videoBufferInfo.size = readSampleSize;
130+
videoBufferInfo.offset = 0;
131+
videoBufferInfo.flags = frameVideoExtractor.getSampleFlags();
132+
videoBufferInfo.presentationTimeUs += 1000 * 1000 / frameRate;
133+
134+
muxer.writeSampleData(frameMuxerTrackIndex, videoByteBuffer, videoBufferInfo); //将样本写入
135+
frameVideoExtractor.advance(); //推进到下一个样本,类似快进
136+
}
137+
} catch (IOException e) {
138+
iDetailCallBackListener.failed(e);
139+
Log.e(TAG, "combineTwoVideos: ", e);
140+
} finally {
141+
//释放资源
142+
audioVideoExtractor.release();
143+
frameVideoExtractor.release();
144+
if (muxer != null) {
145+
muxer.release();
146+
}
147+
iDetailCallBackListener.success();
148+
Log.e(TAG, "combineTwoVideos: " );
149+
}
150+
}
151+
152+
}

app/src/main/java/com/aserbao/androidcustomcamera/whole/record/beans/MediaObject.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ public void stopRecord(Context context, MediaObject mediaObject){
103103
}
104104

105105
public MediaPart getCurrentPart() {
106-
/*if (mMediaPart != null)
107-
return mMediaPart;*/
108106
if (mMediaList != null && mMediaList.size() > 0)
109107
mMediaPart = mMediaList.get(mMediaList.size() - 1);
110108
return mMediaPart;

0 commit comments

Comments
 (0)