You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过ExoPlayer获取歌曲艺术家、歌曲名等元数据?

解决ExoPlayer获取音频元数据(艺术家、歌曲名)的问题

嘿,我来帮你搞定这个ExoPlayer获取音频元数据的问题!你当前的代码已经实现了基础的音频播放,但确实缺少处理元数据的逻辑。下面我会一步步告诉你怎么修改代码,拿到你需要的艺术家、歌曲名等信息。

核心思路

ExoPlayer本身支持通过MetadataOutput接口监听元数据回调,不管是本地音频的ID3标签,还是网络电台的ICY元数据,都可以通过这个接口获取。我们需要做的就是:

  • 确保使用的数据源/渲染器支持元数据传递
  • 实现MetadataOutput接口来接收并解析元数据
  • 将这个监听注册到音频渲染器上

具体实现步骤

1. 实现元数据监听类

首先定义一个类来处理元数据的回调,这里我们同时兼容ID3标签(本地或带ID3的流媒体)和ICY元数据(网络电台常用):

private class MyMetadataListener implements MetadataOutput {
    @Override
    public void onMetadata(Metadata metadata) {
        // 遍历所有元数据条目
        for (int i = 0; i < metadata.length(); i++) {
            Metadata.Entry entry = metadata.get(i);
            
            // 处理ID3标签(比如本地MP3或带ID3的流媒体)
            if (entry instanceof Id3Frame) {
                Id3Frame id3Frame = (Id3Frame) entry;
                if (id3Frame instanceof TextInformationFrame) {
                    TextInformationFrame textFrame = (TextInformationFrame) id3Frame;
                    String tagId = textFrame.id;
                    String tagValue = textFrame.value;
                    
                    // 根据标签ID解析对应的内容
                    switch (tagId) {
                        case "TIT2":
                            // 歌曲名
                            Log.d("AudioMetadata", "歌曲名: " + tagValue);
                            break;
                        case "TPE1":
                            // 艺术家
                            Log.d("AudioMetadata", "艺术家: " + tagValue);
                            break;
                        case "TALB":
                            // 专辑名
                            Log.d("AudioMetadata", "专辑名: " + tagValue);
                            break;
                        // 其他需要的标签可以继续添加
                    }
                }
            }
            // 处理ICY元数据(网络电台常用)
            else if (entry instanceof IcyInfo) {
                IcyInfo icyInfo = (IcyInfo) entry;
                String icyTitle = icyInfo.title;
                // 很多电台的ICY标题格式是「艺术家 - 歌曲名」,可以自己拆分
                if (!TextUtils.isEmpty(icyTitle)) {
                    String[] parts = icyTitle.split(" - ", 2);
                    if (parts.length == 2) {
                        Log.d("AudioMetadata", "艺术家: " + parts[0]);
                        Log.d("AudioMetadata", "歌曲名: " + parts[1]);
                    } else {
                        Log.d("AudioMetadata", "电台标题: " + icyTitle);
                    }
                }
            }
        }
    }
}

2. 修改后台播放代码

接下来把你的doInBackground代码修改一下,注册我们的元数据监听。这里我顺便把旧的ExtractorSampleSource替换成了ExoPlayer 2.x推荐的ProgressiveMediaSource(如果你用的是旧版本,也可以给ExtractorSampleSource设置setMetadataOutput,原理一样):

protected Boolean doInBackground(final String... args) {
    try {
        String radioUrl = station.getRadiourl();
        Uri uri = Uri.parse(radioUrl);
        String userAgent = Util.getUserAgent(context, "ExoPlayerDemo");
        
        // 配置OkHttp数据源(保持你原来的配置)
        OkHttpClient okHttpClient = new OkHttpClient();
        DataSource.Factory dataSourceFactory = new OkHttpDataSource.Factory(okHttpClient)
                .setUserAgent(userAgent)
                .setCacheControl(CacheControl.FORCE_NETWORK);
        
        MediaSource mediaSource;
        if (radioUrl.endsWith(".m3u8")) {
            // HLS流用HlsMediaSource
            mediaSource = new HlsMediaSource.Factory(dataSourceFactory)
                    .createMediaSource(uri);
        } else {
            // 普通流媒体/本地文件用ProgressiveMediaSource
            mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
                    .createMediaSource(uri);
        }
        
        // 创建音频渲染器
        MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(
                mediaSource,
                MediaCodecSelector.DEFAULT,
                null,
                true,
                null,
                null,
                AudioCapabilities.getCapabilities(context),
                AudioManager.STREAM_MUSIC);
        
        // 注册元数据监听
        audioRenderer.setMetadataOutput(new MyMetadataListener());
        
        exoPlayer.prepare(audioRenderer);
        return true;
    } catch (IllegalArgumentException | SecurityException | IllegalStateException e) {
        e.printStackTrace();
    }
    return false;
}

额外注意事项

  • 如果你使用的是模块化的ExoPlayer依赖,确保已经引入了exoplayer-metadata模块,这样才能处理各种元数据类型。
  • 有些网络电台可能没有开启ICY元数据,这种情况下你就拿不到对应的信息,这是电台服务器的设置问题,客户端没法解决。
  • 旧版本ExoPlayer的API可能略有不同,但核心都是通过MetadataOutput来监听元数据。

内容的提问来源于stack exchange,提问作者turkce apps

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:00:01