上犹电脑信息网我们一直在努力
您的位置:上犹电脑信息网 > 文件问题 > 开源一款超级好用的mp3剪切器app-mp3文件剪切器

开源一款超级好用的mp3剪切器app-mp3文件剪切器

作者:上犹日期:

返回目录:文件问题

作者:zyl409214686
链接:https://juejin.im/post/5a324f3f5188253da72e7956


该app使用了MD规范,界面风格简洁,功能上mp3剪切铃声制作,实用性比较强。


1、技术介绍


功能上虽然简洁,但是技术上该项目“麻雀虽小,五脏俱全”。

下面从技术层面上做一些简单介绍:

  • 首页使用了CoordinatorLayout+AppBarLayout+DrawerLayout+NavigationView的经典MD设计风格。
  • 项目整体采用了MVP+databinding+rxjava2+rxandroid2+dagger2框架设计,数据缓存使用了greendao。
  • 音频频谱的绘制主要是通过Visualizer中获取到的波形数据来进行绘制。
  • 剪切功能上,mp3剪切核心功能使用了jaudiotagger jar包获取mp3元数据获取字节位置并进行文件io操作生成目标文件。此功能作为重点,本文后续会做详细的说明。
  • 动画方面,欢迎页使用了lottie动画,如感兴趣可以看这篇博客做了详尽的步骤介绍,制作lottie动画并应用到android项目(https://juejin.im/post/5a355cf5f265da433227a53d)。 项目中文件选择页以及关于页面使用了属性动画和属性动画组件AVLoadingIndicatorView(https://github.com/81813780/AVLoadingIndicatorView)。
  • 自定义控件,范围选取控件CustomRangeSeekBar(https://github.com/zyl409214686/CustomRangeSeekBar),不是本文重点可以看之前的博文android 自定义范围选取控件CustomRangeSeekBar(https://www.jianshu.com/p/712c13584636)。


2、使用说明+gif


Step1. 选择mp3文件

开源一款超级好用的mp3剪切器app

Step2. 通过滑块选择剪切范围然后点击剪切按钮


开源一款超级好用的mp3剪切器app



Tips:主界面上可以看到三个按钮,从左到右的功能分别为:

  • 播放\暂停
  • 切换播放的滑块(切换当前播放的位置,前滑块or后滑块)
  • 音乐剪切


mp3剪切实现思想

实现思想主要有两点

  1. 获取mp3开始时间(要剪切的开始时间)所在的文件字节位置及结束时间所在文件的字节位置
  2. 根据开始时间的字节位置和结束时间的字节位置结合源文件生成我们的目标文件


3、mp3剪切技术实现


那么如何来获取mp3开始时间所在文件的字节位置呢? 这里用到了jaudiotagger.jar。

http://www.jthink.net/jaudiotagger/


它的主页是这样描述它的

Jaudiotagger is a Java API for audio metatagging. Both a common API and format specific APIs are available, currently supports reading and writing metadata for:Mp3、Flac、OggVorbis、Mp4、Aiff、Wav、Wma、Dsf

它是一个音频元标记的java库,可以支持mp3等特定格式进行读写元数据操作。

mp3剪切实现细节:

一、我们要做的事通过Jaudiotagger获取到mp3的元数据,通过元数据取到mp3的首帧字节位置以及比特率。然后根据首帧字节位置以及比特率和开始时间可以其对应文件的字节位置。最后得到开始字节位置和结束字节位置。

1.获取mp3元数据

MP3File mp3 = new MP3File(this.mp3File);
//获取mp3的元数据
MP3AudioHeader header = (MP3AudioHeader) mp3.getAudioHeader();


2. 根据元数据获取mp3比特率

//根据元数据获取比特率
long bitRateKbps = header.getBitRateAsNumber();


可能你会问,什么是比特率?

比特率是每秒传输的比特(bit)数


来看我们取mp3比特率的方法看注释

long bitRate = header.getBitRateAsNumber();看该方法源码注释如下:

/**
*
* @return bitrate in kbps, no indicator is provided as to
* whether or not it is vbr
*/
public long getBitRateAsNumber()
{
return bitrate;
}


通过注释得知,此方法返回的比特率单位为kbps(每秒千字节) ,而我们需要的比特率的单位是(每毫秒位),下一步进行单位转换计算。

3. 转换比特率

这里我们需要换算它为每毫秒位数,1字节是8位,1秒是1000毫秒,千字节是1024字节,那么转换后算到的也就是getBitRateAsNumber() *1024L / 8L / 1000L。代码如下:

//计算出开始字节位置
long bitRatebpm = bitRateKbps *1024L / 8L / 1000L * beginTime;


4.计算开始字节

这个值就是开始时间所在文件的字节位置吗?当然不是,我们的mp3文件当中并不只包含音乐的数据,还包含有音乐的信息头数据。

同样我们可以从头信息中取到我们的mp3首帧字节位置。首帧字节位置+每毫秒位为单位比特率,就是我们要的mp3开始字节位置了。

代码如下:

long firstFrameByte = header.getMp3StartByte();
long beginByte = firstFrameByte + beginBitRateBpm;


5. 计算结束字节位置

同理, 利用上面计算出来的开始字节beginType+时间差(剪切结束时间-开始时间)的比特率(单位为每毫秒位)就可以计算出结束的字节位置了,代码入下:

//计算出结束字节位置
long endByte = beginByte + convertKbpsToBpm(bitRateKbps) * (endTime - beginTime);


long endIndex(截取结束字节位置) = beginIndex(截取开始字节位置) + bitRate *1024L / 8L / 1000L(比特率每毫秒位) * (endTime - beginTime)(截取的时长毫秒单位);

二、 有了开始时间的字节位置和结束时间的字节位置,那我们就可以结合源文件生成我们的目标文件拉。

读写文件我们可以使用RandomAccessFile实现随机的读写操作,通过RandomAccessFile.seek()方法调到指定位置。

问题&解决方案

如果我们要操作的mp3文件很大,比如我们截取的字节大小为100MB,这时候我们的app就会因为OOM直接crash掉了。

这里我的解决方案是通过一个缓存数组来限制每次读写的数据大小,每次操作指定大小的数据,这样无论文件多大,我们都不会出现OOM问题啦。

1.首先我们写一个工具方法,以缓存的方式来生成目标文件,源文件读取指定大小的数据读取写入到目标文件,代码如下:

开源一款超级好用的mp3剪切器app

2. 需要根据需要剪切文件的字节大小,分别考虑小于缓存以及大于等于缓存的情况,分别进行操作。

代码如下:

开源一款超级好用的mp3剪切器app

3. 最后要考虑不但要讲mp3乐音帧相关数据写入, 还要讲头信息写入进去,代码如下:

开源一款超级好用的mp3剪切器app

到这里就结束啦,能力有限,写的不对好的地方,请多提意见。

项目计划讲一直进行维护升级,谢谢您的关注!!!

https://github.com/zyl409214686/Mp3Cutter



github APK下载
https://github.com/zyl409214686/Mp3Cutter/blob/master/apk/app-cutter-release.apk
蒲公英 APK下载
https://www.pgyer.com/mp3cutter


单元测试

如果没有手机或其他原因不方便使用app。项目中提供了单元测试和mp3文件,可以通过单元测试来体验mp3剪切功能。

  • laozi.mp3是源mp3
  • test.mp3是运行完单元测试,生成的mp3文件。
  • startTime、endTime为剪切的开始时间及结束时间


开源一款超级好用的mp3剪切器app


推荐阅读

值得细读!学习开源框架的最佳姿势

推荐3个有用的开源项目

又发现2个非常赞的开源项目

这个开源项目,给你一个《Node.js 最佳实践》

可替代Android的6大开源移动操作系统

相关阅读

关键词不能为空
极力推荐

电脑蓝屏_电脑怎么了_win7问题_win10问题_设置问题_文件问题_上犹电脑信息网

关于我们