(资料图片仅供参考)
若有朋友需要WAV 音频裁剪,可以参考我的另外一篇博文——wav 音频裁剪 在android开发中,一说到音视频,程序员第一反应肯定是FFMpeg,但是FFMpeg这个库,又复杂,又性能差,如果只想简单的要个音频裁剪的功能,就要去引入这么大的库,完全不值得。然而自从android api 16之后谷歌就开始在音视频方面进行布局,android 18之后继续丰富音视频编码库,让很多android app在不依赖于繁琐jni就能进行一些基础的音视频开发。下面将是基于android api16的对mp3文件进行裁剪的代码例子。当前由于时间问题,先分享最主流的mp3格式的音频裁剪,以后有时间会分享更多其他音频方面的经验。
//适当的调整SAMPLE_SIZE可以更加精确的裁剪音乐 private static final int SAMPLE_SIZE = 1024 * 200; @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public static boolean clip(String inputPath, String outputPath, int start, int end){ MediaExtractor extractor = null; BufferedOutputStream outputStream = null; try { extractor = new MediaExtractor(); extractor.setDataSource(inputPath); int track = getAudioTrack(extractor); if(track < 0){ return false; } //选择音频轨道 extractor.selectTrack(track); outputStream = new BufferedOutputStream( new FileOutputStream(outputPath), SAMPLE_SIZE); start = start * 1000; end = end * 1000; //跳至开始裁剪位置 extractor.seekTo(start, MediaExtractor.SEEK_TO_PREVIOUS_SYNC); while (true){ ByteBuffer buffer = ByteBuffer.allocate(SAMPLE_SIZE); int sampleSize = extractor.readSampleData(buffer, 0); long timeStamp = extractor.getSampleTime(); // >= 1000000是要裁剪停止和指定的裁剪结尾不小于1秒,否则可能产生需要9秒音频 //裁剪到只有8.6秒,大多数音乐播放器是向下取整,这样对于播放器变成了8秒, // 所以要裁剪比9秒多一秒的边界 if(timeStamp > end && timeStamp - end >= 1000000){ break; } if(sampleSize <= 0){ break; } byte[] buf = new byte[sampleSize]; buffer.get(buf, 0, sampleSize); //写入文件 outputStream.write(buf); //音轨数据往前读 extractor.advance(); } } catch (IOException e) { e.printStackTrace(); }finally { if(extractor != null){ extractor.release(); } if(outputStream != null){ try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return true; } /** * 获取音频数据轨道 * @param extractor * @return */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private static int getAudioTrack(MediaExtractor extractor) { for(int i = 0; i < extractor.getTrackCount(); i++){ MediaFormat format = extractor.getTrackFormat(i); String mime = format.getString(MediaFormat.KEY_MIME); if(mime.startsWith("audio")){ return i; } } return -1; }
裁剪音乐的步骤在注释中已经写得很明白了,其实用上面简单的代码就能实现音频裁剪了,而且裁剪的音频经过多项硬指标测试是没有问题的。但可能还是有人会怀疑用上述方法是否得到一个“真正”mp3文件。绝大部分情况下,产品经理的需求都是希望裁剪后的音乐除了长度之外,其他的都和原始音频一样,以防不同的播放器由于编解码库的差异,导致播放失败的情况。下面的代码是用来提取音频的关键数据,来比较裁剪之后的音频和原始音频的关键数据是否一样。
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)private static void printMusicFormat(String musicPath){ try { MediaExtractor extractor = new MediaExtractor(); extractor.setDataSource(musicPath); MediaFormat format = extractor.getTrackFormat(getAudioTrack(extractor)); Log.i("music", "码率:" + format.getInteger(MediaFormat.KEY_BIT_RATE)); Log.i("music", "轨道数:" + format.getInteger(MediaFormat.KEY_CHANNEL_COUNT)); Log.i("music", "采样率:" + format.getInteger(MediaFormat.KEY_SAMPLE_RATE)); } catch (IOException e) { e.printStackTrace(); }}
通过反复验证,通过以上方法裁剪的音频除了时间长度之外,其他格式数据都和原始音频一样,裁剪的音频在各种平台(android, IOS, windows,mac)都能正常的播放和使用。