├── src └── com │ └── musicplus │ ├── .gitignore │ ├── media │ ├── MediaConstants.java │ ├── AudioEncoder.java │ ├── AudioDecoder.java │ ├── MediaUtils.java │ ├── MultiAudioMixer.java │ ├── AndroidAudioDecoder.java │ ├── VideoRecorder.java │ ├── AACAudioEncoder.java │ ├── CameraHelper.java │ ├── MultiRawAudioPlayer.java │ └── VideoMuxer.java │ ├── app │ ├── ui │ │ ├── BaseActivity.java │ │ ├── MainActivity.java │ │ ├── AudioChooserActivity.java │ │ ├── MixAudioActivity.java │ │ └── ComposeActivity.java │ ├── service │ │ ├── MusicPlayInterface.java │ │ └── LocalMusicPlayService.java │ └── MainApplication.java │ ├── utils │ ├── DLog.java │ └── MD5Util.java │ └── entry │ └── AudioEntry.java ├── preview.png ├── ic_launcher-web.png ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ ├── ic_launcher.png │ ├── ic_play_normal.png │ ├── ic_stop_normal.png │ ├── ic_delete_normal.png │ ├── ic_delete_pressed.png │ ├── ic_play_pressed.png │ └── ic_stop_pressed.png ├── drawable-xxhdpi │ └── ic_launcher.png ├── values │ ├── colors.xml │ ├── dimens.xml │ ├── styles.xml │ └── strings.xml ├── drawable │ ├── listitem_selector.xml │ ├── ic_play.xml │ ├── ic_stop.xml │ └── ic_delete.xml ├── layout │ ├── activity_list.xml │ ├── activity_main.xml │ ├── activity_mix_audio.xml │ ├── listitem_audio_info.xml │ └── activity_compose.xml ├── values-v11 │ └── styles.xml ├── menu │ └── main.xml ├── values-w820dp │ └── dimens.xml └── values-v14 │ └── styles.xml ├── .settings └── org.eclipse.jdt.core.prefs ├── README.md ├── .classpath ├── .gitignore ├── .project ├── AndroidManifest.xml └── LICENSE /src/com/musicplus/.gitignore: -------------------------------------------------------------------------------- 1 | /tester 2 | -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/preview.png -------------------------------------------------------------------------------- /ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/ic_launcher-web.png -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_play_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-xhdpi/ic_play_normal.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_stop_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-xhdpi/ic_stop_normal.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_delete_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-xhdpi/ic_delete_normal.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_delete_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-xhdpi/ic_delete_pressed.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_play_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-xhdpi/ic_play_pressed.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_stop_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YeDaxia/MusicPlus/HEAD/res/drawable-xhdpi/ic_stop_pressed.png -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 3 | org.eclipse.jdt.core.compiler.compliance=1.6 4 | org.eclipse.jdt.core.compiler.source=1.6 5 | -------------------------------------------------------------------------------- /src/com/musicplus/media/MediaConstants.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.media; 2 | 3 | public interface MediaConstants { 4 | int AUDIO_CHANNEL = 2; 5 | int AUDIO_SAMPLE_RATE = 44100; 6 | 7 | int VIDEO_FRAME_RATE = 25; 8 | } 9 | -------------------------------------------------------------------------------- /res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFFFF 4 | #FF000000 5 | #FFCCCCCC 6 | 7 | -------------------------------------------------------------------------------- /res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16dp 5 | 16dp 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/com/musicplus/app/ui/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.app.ui; 2 | 3 | import android.app.Activity; 4 | import android.view.View; 5 | 6 | abstract class BaseActivity extends Activity{ 7 | 8 | @SuppressWarnings("unchecked") 9 | public T findView(int id) { 10 | return (T) findViewById(id); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /res/drawable/listitem_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /res/layout/activity_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /res/drawable/ic_play.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /res/drawable/ic_stop.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /res/drawable/ic_delete.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 64dp 9 | 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 音频处理另外一个更完整的项目:https://github.com/YeDaxia/AndroidAudioMixer 2 | 3 | # MusicPlus 4 | MusicPlus基于MediaExtractor、MediaMuxer、和MediaCodec等工具类,来实现了对视频中音频的提取,然后和其他音频进行混音后,再用新的音频来合成新的视频。如果你对于音频格式之间的转换感兴趣,比如WAV转ACC格式,也可以在其中找到相关的代码。 5 | 6 | # Note 7 | 1. 由于视频录制的时候会把播放的背景音乐一起录进去,因此在录制包含视频音轨的视频时,记得带上耳机。 8 | 2. 更多介绍: http://www.darcye.com/article/00301860 9 | 10 | # 截图 11 | ![image](https://github.com/YeDaxia/MusicPlus/blob/master/preview.png) 12 | -------------------------------------------------------------------------------- /res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/com/musicplus/media/AudioEncoder.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.media; 2 | 3 | 4 | public abstract class AudioEncoder { 5 | 6 | String rawAudioFile; 7 | 8 | AudioEncoder(String rawAudioFile){ 9 | this.rawAudioFile = rawAudioFile; 10 | } 11 | 12 | public static AudioEncoder createAccEncoder(String rawAudioFile){ 13 | return new AACAudioEncoder(rawAudioFile); 14 | } 15 | 16 | public abstract void encodeToFile(String outEncodeFile); 17 | } 18 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/com/musicplus/app/service/MusicPlayInterface.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.app.service; 2 | 3 | import android.net.Uri; 4 | 5 | public interface MusicPlayInterface { 6 | /** 7 | * to play an audio 8 | * @param audioUri 9 | */ 10 | void play(Uri audioUri); 11 | 12 | /** 13 | * to pause the play 14 | */ 15 | void pause(); 16 | 17 | /** 18 | * Starts or resumes playback. If playback had previously been paused, 19 | * playback will continue from where it was paused. If playback had been stopped, 20 | * or never started before, playback will start at the beginning. 21 | */ 22 | void start(); 23 | 24 | /** 25 | * to release the resource 26 | */ 27 | void close(); 28 | } 29 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/com/musicplus/utils/DLog.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.utils; 2 | 3 | import android.util.Log; 4 | 5 | public class DLog { 6 | 7 | private static boolean debug = true; 8 | 9 | private static final String TAG = "com.darcymusic"; 10 | 11 | public static void i(String tag, String msg){ 12 | if(debug) 13 | Log.i(tag, msg); 14 | } 15 | 16 | public static void i(String msg){ 17 | if(debug) 18 | Log.i(TAG, msg); 19 | } 20 | 21 | public static void w(String tag, String msg){ 22 | if(debug) 23 | Log.w(tag, msg); 24 | } 25 | 26 | public static void w(String msg){ 27 | if(debug) 28 | Log.w(TAG, msg); 29 | } 30 | 31 | public static void e(String tag, String msg){ 32 | if(debug) 33 | Log.e(tag, msg); 34 | } 35 | 36 | public static void e(String msg){ 37 | if(debug) 38 | Log.e(TAG, msg); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/com/musicplus/entry/AudioEntry.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.entry; 2 | 3 | import java.io.Serializable; 4 | 5 | public class AudioEntry implements Serializable{ 6 | 7 | private static final long serialVersionUID = 2178420052691000209L; 8 | 9 | public long id; 10 | public String fileName; 11 | public String title; 12 | public int duration; 13 | public String artist; 14 | public String album; 15 | public String year; 16 | public String mime; 17 | public String size; 18 | public String fileUrl; 19 | 20 | public boolean isPlaying; 21 | 22 | @Override 23 | public int hashCode() { 24 | return Long.valueOf(id).hashCode(); 25 | } 26 | 27 | @Override 28 | public boolean equals(Object obj) { 29 | if(obj == null) 30 | return false; 31 | if(obj == this) 32 | return true; 33 | return obj instanceof AudioEntry && ((AudioEntry)obj).id == this.id; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Android generated 2 | bin 3 | gen 4 | proguard 5 | 6 | #IntelliJ IDEA 7 | .idea 8 | *.iml 9 | classes 10 | 11 | #Command line 12 | build.xml 13 | proguard-project.txt 14 | 15 | 16 | build 17 | .gradle 18 | 19 | ##############my configs 20 | # built application files 21 | *.apk 22 | *.ap_ 23 | 24 | # files for the dex VM 25 | *.dex 26 | 27 | # Java class files 28 | *.class 29 | 30 | # generated files 31 | bin/ 32 | gen/ 33 | proguard/ 34 | 35 | # Local configuration file (sdk path, etc) 36 | local.properties 37 | 38 | *.pydevproject 39 | .metadata 40 | bin/** 41 | tmp/** 42 | tmp/**/* 43 | *.tmp 44 | *.bak 45 | *.swp 46 | *~.nib 47 | local.properties 48 | .loadpath 49 | 50 | # External tool builders 51 | .externalToolBuilders/ 52 | 53 | # Locally stored "Eclipse launch configurations" 54 | *.launch 55 | 56 | # CDT-specific 57 | .cproject 58 | 59 | # PDT-specific 60 | .buildpath 61 | .DS_Store 62 | project.properties -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | MusicPlus 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Music++ 5 | Hello world! 6 | Settings 7 | 8 | 录制 9 | 预览 10 | 重录 11 | 添加音轨 12 | 完成录制 13 | 不包含视频音轨 14 | 包含视频音轨 15 | 单纯混音 16 | 可能要耗时比较长,请耐心等待 17 | 合成视频成功 18 | 开始混音 19 | 播放混音 20 | 暂停播放 21 | 继续播放 22 | 23 | -------------------------------------------------------------------------------- /src/com/musicplus/app/ui/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.app.ui; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | 7 | import com.musicplus.R; 8 | 9 | public class MainActivity extends BaseActivity{ 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_main); 15 | } 16 | 17 | public void onExcludeClick(View v){ 18 | Intent composeIntent = new Intent(this, ComposeActivity.class); 19 | composeIntent.putExtra(ComposeActivity.EX_INCLUDE_VIDEO_AUDIO, false); 20 | startActivity(composeIntent); 21 | } 22 | 23 | public void onIncludeClick(View v){ 24 | Intent composeIntent = new Intent(this, ComposeActivity.class); 25 | composeIntent.putExtra(ComposeActivity.EX_INCLUDE_VIDEO_AUDIO, true); 26 | startActivity(composeIntent); 27 | } 28 | 29 | public void onMixAudioClick(View v){ 30 | Intent mixAudioIntent = new Intent(this, MixAudioActivity.class); 31 | startActivity(mixAudioIntent); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/com/musicplus/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | 2 | package com.musicplus.utils; 3 | 4 | import java.security.MessageDigest; 5 | 6 | /************************************************* 7 | * md5 类实现了RSA Data Security, Inc.在提交给IETF 的RFC1321中的MD5 message-digest 算法。 8 | *************************************************/ 9 | 10 | public class MD5Util { 11 | 12 | public static String getMD5Str(String src) { 13 | try { 14 | MessageDigest messageDigest = MessageDigest.getInstance("MD5"); 15 | messageDigest.update(src.getBytes()); 16 | return toHexString(messageDigest.digest()); 17 | } catch (Exception e) { 18 | } 19 | return null; 20 | } 21 | 22 | private static String toHexString(byte[] b) { 23 | StringBuilder sb = new StringBuilder(b.length * 2); 24 | for (int i = 0; i < b.length; i++) { 25 | sb.append(Digit[(b[i] & 0xf0) >>> 4]); 26 | sb.append(Digit[b[i] & 0x0f]); 27 | } 28 | return sb.toString(); 29 | } 30 | 31 | private static char[] Digit = { 32 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 33 | }; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/com/musicplus/media/AudioDecoder.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.media; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * 音频解码器 7 | * @author Darcy 8 | * 9 | */ 10 | public abstract class AudioDecoder { 11 | 12 | String mEncodeFile; 13 | 14 | OnAudioDecoderListener mOnAudioDecoderListener; 15 | 16 | AudioDecoder(String encodefile){ 17 | this.mEncodeFile = encodefile; 18 | } 19 | 20 | public static AudioDecoder createDefualtDecoder(String encodefile){ 21 | return new AndroidAudioDecoder(encodefile); 22 | } 23 | 24 | public void setOnAudioDecoderListener(OnAudioDecoderListener l ){ 25 | this.mOnAudioDecoderListener = l; 26 | } 27 | 28 | /** 29 | * 解码 30 | * @return 31 | * @throws IOException 32 | */ 33 | public abstract RawAudioInfo decodeToFile(String outFile) throws IOException; 34 | 35 | public static class RawAudioInfo{ 36 | public String tempRawFile; 37 | public int size; 38 | public long sampleRate; 39 | public int channel; 40 | } 41 | 42 | public interface OnAudioDecoderListener{ 43 | /** 44 | * monitor when processing decode 45 | * @param decodedBytes 46 | * @param progress range 0~1 47 | * @throws IOException 48 | */ 49 | void onDecode(byte[] decodedBytes, double progress) throws IOException; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/com/musicplus/app/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.musicplus.app; 2 | 3 | import java.io.File; 4 | 5 | import android.app.Application; 6 | import android.os.Environment; 7 | 8 | public class MainApplication extends Application{ 9 | 10 | private static final String SD_ROOT = Environment.getExternalStorageDirectory().getPath(); 11 | public static final String APP_EXTERNAL_ROOT_PATH = SD_ROOT + "/MusicPlus"; 12 | public static final String TEMP_FILE_PATH = APP_EXTERNAL_ROOT_PATH + "/temp"; 13 | public static final String TEMP_AUDIO_PATH = TEMP_FILE_PATH + "/audio"; 14 | public static final String TEMP_VIDEO_PATH = TEMP_FILE_PATH + "/video"; 15 | public static final String RECORD_AUDIO_PATH = APP_EXTERNAL_ROOT_PATH + "/audio"; 16 | public static final String RECORD_VIDEO_PATH = APP_EXTERNAL_ROOT_PATH + "/video"; 17 | 18 | @Override 19 | public void onCreate() { 20 | super.onCreate(); 21 | createStoreDirs(); 22 | } 23 | 24 | private void createStoreDirs(){ 25 | File tempAudioDir = new File(TEMP_AUDIO_PATH); 26 | if(!tempAudioDir.exists()){ 27 | tempAudioDir.mkdirs(); 28 | } 29 | File tempVideoDir = new File(TEMP_VIDEO_PATH); 30 | if(!tempVideoDir.exists()){ 31 | tempVideoDir.mkdir(); 32 | } 33 | File recordAudioPath = new File(RECORD_AUDIO_PATH); 34 | if(!recordAudioPath.exists()){ 35 | recordAudioPath.mkdir(); 36 | } 37 | File recordVideoPath = new File(RECORD_VIDEO_PATH); 38 | if(!recordVideoPath.exists()){ 39 | recordVideoPath.mkdir(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 |