Android-Audio-MediaPlayer和AudioTrack播放区别

MediaPlayer 与 AudioTrack 播放区别

  1. 架构层级对比

MediaPlayer: 应用层 → Java Framework → Native层 → 解码器 → AudioTrack → 硬件

└── 完整的播放器解决方案

AudioTrack: 应用层 → Java Framework → AudioFlinger → HAL → 硬件

└── 纯粹的音频输出通道

  1. 功能定位差异

MediaPlayer

// 高级API,支持多种媒体格式

MediaPlayer mp = new MediaPlayer();

mp.setDataSource("audio.mp3"); // 或视频文件、网络流

mp.prepare();

mp.start(); // 自动处理解码、同步、输出

AudioTrack

// 低级API,只处理PCM数据输出

AudioTrack track = new AudioTrack.Builder()

.setAudioFormat(format)

.setBufferSizeInBytes(bufferSize)

.build();

byte[] pcmData = decodeAudio(); // 需要自己解码

track.write(pcmData, 0, pcmData.length); // 手动写入PCM

track.play();

  1. 支持格式对比

MediaPlayer 支持格式

// 支持所有Android系统支持的编码格式

支持的音频格式: MP3, AAC, WAV, OGG, FLAC, MIDI等

支持的视频格式: MP4, 3GP, WebM, MKV等

支持的协议: HTTP, HTTPS, RTSP, FILE, ASSET等

// 自动检测和解码

mp.setDataSource(context, uri); // 自动识别格式

AudioTrack 支持格式

// 只支持PCM原始数据

支持的格式:

  • ENCODING_PCM_8BIT
  • ENCODING_PCM_16BIT
  • ENCODING_PCM_FLOAT
  • ENCODING_AC3
  • ENCODING_E_AC3
  • ENCODING_DTS
  • ENCODING_DTS_HD
  • ENCODING_IEC61937

// 必须自己解码

AudioFormat format = new AudioFormat.Builder()

.setEncoding(AudioFormat.ENCODING_PCM_16BIT) // 必须是PCM

.setSampleRate(44100)

.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)

.build();

  1. 解码能力对比

MediaPlayer 解码流程

// 完整的解码管道

MediaPlayer内部结构:

  1. 数据源读取器 (DataSource)
  2. 解复用器 (Demuxer)
  3. 音频解码器 (AudioDecoder)
  4. 视频解码器 (VideoDecoder, 可选)
  5. 音视频同步器 (AVSync)
  6. 音频渲染器 (AudioTrack内部使用)
  7. 视频渲染器 (SurfaceView/TextureView)

// 自动硬解/软解选择

mp.setDataSource(...);

mp.prepare(); // 自动选择最佳解码器

AudioTrack 无解码能力

// 需要手动解码

// 示例:使用MediaCodec手动解码后传给AudioTrack

// 1. 创建解码器

MediaCodec codec = MediaCodec.createDecoderByType("audio/mp4a-latm");

// 2. 配置解码器

MediaFormat format = MediaFormat.createAudioFormat(

"audio/mp4a-latm", 44100, 2);

codec.configure(format, null, null, 0);

// 3. 解码循环

codec.start();

ByteBuffer[] inputBuffers = codec.getInputBuffers();

ByteBuffer[] outputBuffers = codec.getOutputBuffers();

while (true) {

// 输入压缩数据

int inputIndex = codec.dequeueInputBuffer(timeout);

if (inputIndex >= 0) {

ByteBuffer buffer = inputBuffers[inputIndex];

// 填充压缩数据...

codec.queueInputBuffer(inputIndex, ...);

}

复制代码
// 获取解码后的PCM
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
int outputIndex = codec.dequeueOutputBuffer(info, timeout);
if (outputIndex >= 0) {
    ByteBuffer buffer = outputBuffers[outputIndex];
    byte[] pcmData = new byte[info.size];
    buffer.get(pcmData);
    
    // 4. 写入AudioTrack
    audioTrack.write(pcmData, 0, pcmData.length);
    
    codec.releaseOutputBuffer(outputIndex, false);
}

}

  1. 使用复杂度对比

MediaPlayer 简单易用

// 几行代码完成播放

public class SimplePlayer {

private MediaPlayer player;

复制代码
public void play(String url) {
    player = new MediaPlayer();
    player.setDataSource(url);
    player.prepareAsync();
    player.setOnPreparedListener(mp -> mp.start());
    
    // 自动处理:
    // 1. 缓冲
    // 2. 错误恢复
    // 3. 播放完成
    // 4. 音视频同步
}

}

AudioTrack 复杂但灵活

// 需要自己管理整个流程

public class CustomAudioPlayer {

private AudioTrack audioTrack;

private MediaExtractor extractor;

private MediaCodec decoder;

private Thread decodeThread;

复制代码
public void play(String audioFile) {
    // 1. 创建AudioTrack
    setupAudioTrack();
    
    // 2. 创建解复用器
    extractor = new MediaExtractor();
    extractor.setDataSource(audioFile);
    
    // 3. 选择音轨和创建解码器
    setupDecoder();
    
    // 4. 启动解码线程
    decodeThread = new Thread(this::decodeLoop);
    decodeThread.start();
    
    // 需要手动处理:
    // 1. 缓冲管理
    // 2. 播放控制
    // 3. 错误处理
    // 4. 资源释放
}

private void decodeLoop() {
    // 复杂的解码循环...
    while (!stopped) {
        // 解码逻辑...
        // 写入AudioTrack...
    }
}

}

  1. 性能特性对比

MediaPlayer 性能特点

// 优点:优化好,稳定性高

  1. 系统级优化
  2. 硬件解码支持
  3. 功耗管理
  4. 音视频同步
  5. 后台播放支持

// 缺点:定制性差

  1. 无法控制解码过程
  2. 延迟较高(50-200ms)
  3. 无法直接访问PCM数据

AudioTrack 性能特点

// 优点:低延迟,高灵活性

  1. 极低延迟(可做到10ms以下)
  2. 直接访问PCM数据
  3. 可自定义处理(如音效、混音)
  4. 精确的播放控制

// 缺点:复杂度高

  1. 需要手动解码

  2. 需要管理缓冲区

  3. 需要处理同步

  4. 功耗管理需要自己实现

  5. 延迟对比

MediaPlayer 延迟

// 典型延迟:50ms - 200ms

延迟来源:

  1. 解码器缓冲 (20-50ms)
  2. AudioTrack缓冲 (20-50ms)
  3. 同步缓冲 (10-30ms)
  4. 系统调度 (10-50ms)

// 不可调整

mp.setAudioAttributes(new AudioAttributes.Builder()

.setFlags(AudioAttributes.FLAG_LOW_LATENCY) // 有限效果

.build());

AudioTrack 低延迟配置

// 可达到10ms以下延迟

AudioTrack track = new AudioTrack.Builder()

.setAudioAttributes(new AudioAttributes.Builder()

.setUsage(AudioAttributes.USAGE_MEDIA)

.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)

.setFlags(AudioAttributes.FLAG_LOW_LATENCY)

.build())

.setAudioFormat(new AudioFormat.Builder()

.setEncoding(AudioFormat.ENCODING_PCM_16BIT)

.setSampleRate(48000)

.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)

.build())

.setBufferSizeInBytes(AudioTrack.getMinBufferSize(

48000,

AudioFormat.CHANNEL_OUT_STEREO,

AudioFormat.ENCODING_PCM_16BIT))

.setPerformanceMode(AudioTrack.PERFORMANCE_MODE_LOW_LATENCY)

.setTransferMode(AudioTrack.MODE_STREAM)

.build();

// 直接模式(Android 8.0+)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

track.setPreferredDevice(AudioManager.getDevices(

AudioManager.GET_DEVICES_OUTPUTS)[0]);

}

  1. 适用场景对比

适合使用 MediaPlayer 的场景

// 1. 标准媒体播放

mp.setDataSource("http://example.com/audio.mp3");

mp.start(); // 播放音乐/播客

// 2. 视频播放(带音频)

mp.setDisplay(surfaceHolder);

mp.setDataSource("video.mp4");

mp.start(); // 播放视频,自动处理音视频同步

// 3. 流媒体播放

mp.setDataSource("rtsp://stream.example.com/live");

mp.prepareAsync(); // 支持RTSP/HTTP流

// 4. 后台播放

mp.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);

mp.setAudioAttributes(new AudioAttributes.Builder()

.setUsage(AudioAttributes.USAGE_MEDIA)

.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)

.build());

适合使用 AudioTrack 的场景

// 1. 实时音频处理(语音通话、VOIP)

public class VoiceChatPlayer {

public void playRealTimeAudio(byte[] pcmData) {

// 极低延迟播放

audioTrack.write(pcmData, 0, pcmData.length);

}

}

// 2. 音频合成/生成

public class ToneGenerator {

public void playSineWave(float frequency, int duration) {

byte[] pcm = generateSineWave(frequency, duration);

audioTrack.write(pcm, 0, pcm.length);

}

}

// 3. 专业音频应用(DAW、混音器)

public class AudioMixer {

public void mixAndPlay(List clips) {

byte[] mixed = mixAudioClips(clips);

audioTrack.write(mixed, 0, mixed.length);

}

}

// 4. 游戏音效(需要精确控制)

public class GameAudioEngine {

public void playSoundEffect(int soundId, float volume, float pan) {

byte[] pcm = soundPool.getPcm(soundId);

applyEffects(pcm, volume, pan); // 实时音效处理

audioTrack.write(pcm, 0, pcm.length);

}

}

  1. 资源消耗对比

MediaPlayer 资源管理

// 自动管理资源

mp.setOnCompletionListener(mp -> {

mp.release(); // 自动释放解码器、AudioTrack等资源

});

// 后台播放时系统会管理资源

mp.setAudioAttributes(new AudioAttributes.Builder()

.setUsage(AudioAttributes.USAGE_MEDIA)

.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)

.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)

.build());

AudioTrack 资源管理

// 需要手动管理

public class CustomPlayer {

private AudioTrack track;

复制代码
public void play() {
    track = createAudioTrack();
    // 需要自己管理:
    // 1. 解码器资源
    // 2. 内存缓冲
    // 3. 线程管理
    // 4. 错误恢复
}

public void stop() {
    track.stop();
    track.release();  // 必须手动释放
    // 还需要释放解码器、线程等
}

}

  1. 选择建议

选择 MediaPlayer 的情况

// 当需要:

if (needStandardPlayback ||

needVideoSupport ||

needNetworkStreaming ||

needBackgroundPlayback ||

needFormatCompatibility ||

!haveAudioExpertise) {

// 使用 MediaPlayer

MediaPlayer player = new MediaPlayer();

}

选择 AudioTrack 的情况

// 当需要:

if (needLowLatency ||

needDirectPCMAccess ||

needCustomAudioProcessing ||

needRealTimeSynthesis ||

buildingProAudioApp ||

haveSpecificDecodingNeeds) {

// 使用 AudioTrack + 自定义解码

AudioTrack track = new AudioTrack(...);

// 配合 MediaCodec/自定义解码器

}

  1. 混合使用方案

// 在某些场景下可以混合使用

public class HybridPlayer {

private MediaPlayer mediaPlayer;

private AudioTrack audioTrack;

复制代码
// 使用MediaPlayer解码,AudioTrack播放(获取PCM数据)
public void playWithPCMAccess(String file) {
    // 1. 用MediaPlayer解码但静音
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setDataSource(file);
    mediaPlayer.setVolume(0, 0);  // 静音
    
    // 2. 用AudioTrack播放(可添加效果)
    audioTrack = createAudioTrackWithEffects();
    
    // 3. 获取PCM数据(需要系统权限或特定API)
    // 这通常需要系统级修改或特定ROM支持
}

// 或者:用AudioTrack播放,但用MediaPlayer做fallback
public void playWithFallback(String file) {
    try {
        playWithAudioTrack(file);
    } catch (UnsupportedFormatException e) {
        // 格式不支持,fallback到MediaPlayer
        playWithMediaPlayer(file);
    }
}

}

总结对比表

特性 MediaPlayer AudioTrack

解码支持 内置解码器,支持多种格式 无解码,只支持PCM

使用复杂度 简单,高级API 复杂,低级API

延迟 较高 (50-200ms) 极低 (可<10ms)

灵活性 低,封装完整 高,完全可控

资源管理 自动管理 手动管理

适用场景 标准媒体播放、视频 实时音频、专业应用

系统集成 完整(通知、后台、耳机控制) 基本音频输出

格式支持 所有系统支持的格式 仅PCM格式

缓冲管理 自动缓冲 手动缓冲管理

同步支持 自动音视频同步 无同步,需要自己实现

简单选择原则:

• 普通播放需求 → MediaPlayer

• 专业音频处理 → AudioTrack

• 视频播放 → MediaPlayer

• 实时语音/游戏音效 → AudioTrack

• 快速开发 → MediaPlayer

• 性能优化 → AudioTrack

相关推荐
BduL OWED2 小时前
mysql的主从配置
android·mysql·adb
人需要PID3 小时前
【卡尔曼工具箱-EKF-MATLAB应用】
android
亘元有量-流量变现4 小时前
APP自动识别跳转各大应用商店(鸿蒙+iOS+安卓全品牌)|可直接部署落地页源码
android·ios·harmonyos
ForteScarlet8 小时前
从 Kotlin 编译器 API 的变化开始: 2.3.20
android·开发语言·后端·ios·开源·kotlin
私人珍藏库8 小时前
[Android] 假装来电 v1.1.0
android·app·工具·软件·多功能
spencer_tseng9 小时前
Android Studio [Gradle JDK]
android·ide·android studio
sun0077009 小时前
wifi热点的防火墙
android
Code-Porter10 小时前
记录关于Flutter ObjectBox数据库使用ObjectBoxBrowser插件,在同一个局域网内电脑无法访问查看数据问题
android·数据库·flutter·dart
KongHen0210 小时前
Android Studio最新版汉化教程(2025年10月17日)
android·ide·android studio