在Android Studio中如何修剪音乐文件?求可用库及实现方法
Android 音乐文件裁剪实现方案
方法一:使用Android原生API(MediaExtractor + MediaMuxer)
无需依赖第三方库,通过系统原生媒体API实现裁剪,适合不想引入额外依赖的场景。
核心逻辑
- 用
MediaExtractor读取源音频,定位到音频轨道; - 将裁剪时间转换为毫秒(比如30秒=30000ms、50秒=50000ms),定位到起始时间点;
- 用
MediaMuxer创建输出文件,将截取的音频数据写入新文件,直到达到结束时间。
代码示例
import android.media.MediaExtractor import android.media.MediaFormat import android.media.MediaMuxer import java.io.IOException fun trimAudio(sourcePath: String, outputPath: String, startMs: Long, endMs: Long) { val extractor = MediaExtractor() var muxer: MediaMuxer? = null var trackIndex = -1 var sampleTime: Long try { extractor.setDataSource(sourcePath) // 遍历找到音频轨道 for (i in 0 until extractor.trackCount) { val format = extractor.getTrackFormat(i) val mime = format.getString(MediaFormat.KEY_MIME) if (mime?.startsWith("audio/") == true) { trackIndex = i extractor.selectTrack(i) // 初始化MediaMuxer准备写入 muxer = MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) val muxerTrackIndex = muxer.addTrack(format) muxer.start() break } } if (trackIndex == -1) throw IOException("源文件中未找到音频轨道") // 定位到裁剪起始时间点 extractor.seekTo(startMs, MediaExtractor.SEEK_TO_CLOSEST_SYNC) val buffer = ByteArray(1024 * 1024) while (true) { sampleTime = extractor.sampleTime // 超过结束时间则停止 if (sampleTime > endMs) break val sampleSize = extractor.readSampleData(buffer, 0) if (sampleSize < 0) break val bufferInfo = MediaMuxer.OutputBufferInfo().apply { offset = 0 size = sampleSize presentationTimeUs = sampleTime flags = extractor.sampleFlags } muxer?.writeSampleData(0, buffer, bufferInfo) extractor.advance() } } catch (e: IOException) { e.printStackTrace() } finally { extractor.release() muxer?.stop() muxer?.release() } } // 调用示例:截取30秒到50秒的片段 trimAudio( sourcePath = "/sdcard/Music/source.mp3", outputPath = "/sdcard/Music/trimmed.mp3", startMs = 30 * 1000, endMs = 50 * 1000 )
方法二:使用FFmpeg第三方库
如果原生API对部分格式支持有限,FFmpeg是兼容性更强的选择,支持几乎所有音频格式。
步骤
- 引入FFmpeg的Android封装库;
- 执行裁剪命令,指定起始/结束时间和输出路径。
代码示例
首先在build.gradle中添加依赖:
dependencies { implementation 'com.arthenica:ffmpeg-kit-full:5.1.LTS' }
执行裁剪逻辑:
import com.arthenica.ffmpegkit.FFmpegKit import com.arthenica.ffmpegkit.FFmpegSession fun trimAudioWithFFmpeg(sourcePath: String, outputPath: String, startSec: Int, endSec: Int) { // -ss 指定起始时间,-to 指定结束时间,-c copy 直接复制编码(快速无损失) val command = "-i $sourcePath -ss $startSec -to $endSec -c copy $outputPath" val session = FFmpegKit.execute(command) when (session.returnCode.value) { 0 -> { // 裁剪成功 } else -> { // 错误处理,可通过session.failStackTrace获取详情 } } } // 调用示例 trimAudioWithFFmpeg( sourcePath = "/sdcard/Music/source.mp3", outputPath = "/sdcard/Music/trimmed_ffmpeg.mp3", startSec = 30, endSec = 50 )
注意事项
- 权限申请:Android 13及以上需申请
READ_MEDIA_AUDIO和WRITE_EXTERNAL_STORAGE(针对公共存储目录),并做好动态权限申请; - 格式适配:原生API对小众格式支持有限,FFmpeg兼容性更优;
- 性能差异:原生API更轻量,FFmpeg功能全但会增加APK体积。
内容的提问来源于stack exchange,提问作者Khang Pham
相关产品推荐
相关产品推荐

