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

相关推荐
私房菜40 分钟前
Selinux 及在Android 的使用详解
android·selinux·sepolicy
一只特立独行的Yang1 小时前
Android中的系统级共享库
android
两个人的幸福online2 小时前
php开发者 需要 协程吗
android·开发语言·php
修炼者3 小时前
WindowManager(WMS)构建全局悬浮窗
android
xiaoshiquan12063 小时前
Android Studio里,SDK Manager显示不全问题
android·ide·android studio
Lstone73644 小时前
Bitmap深入分析(一)
android
一起搞IT吧5 小时前
Android功耗系列专题理论之十四:Sensor功耗问题分析方法
android·c++·智能手机·性能优化
ByNotD0g5 小时前
Doris 学习笔记
android·笔记·学习
修炼者5 小时前
【Android进阶】 RenderEffect的底层实现
android