本地音乐播放器应用


欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

适配的第三方库地址:

  • audioplayers: https://pub.dev/packages/audioplayers
  • audio_service: https://pub.dev/packages/audio_service
  • audio_session: https://pub.dev/packages/audio_session
  • path_provider: https://pub.dev/packages/path_provider
  • permission_handler: https://pub.dev/packages/permission_handler

一、项目概述

运行效果图

image-20260412100620321

image-20260412100627341

image-20260412100637586

image-20260412100642581

image-20260412100650511

1.1 应用简介

本地音乐播放器是一款功能完善的音乐播放应用,致力于为用户提供纯净、流畅的音乐聆听体验。应用支持扫描设备本地音乐文件,提供播放列表管理、歌词显示、均衡器调节等功能,支持后台播放,让用户随时随地享受高品质音乐。

应用以活力四射的粉红色为主色调,象征音乐的热情与活力。涵盖音乐列表、播放列表、均衡器、设置四大模块。用户可以浏览本地音乐、创建个性化歌单、调节音效、管理播放设置,打造专属的音乐空间。

1.2 核心功能

功能模块 功能描述 实现方式
音乐扫描 扫描设备本地音乐文件 文件系统遍历
播放控制 播放、暂停、上下曲切换 音频引擎
歌词显示 同步滚动歌词展示 LRC解析
均衡器 五段均衡器调节 音频处理
播放列表 创建和管理歌单 本地存储
后台播放 支持后台持续播放 后台服务
播放模式 顺序、循环、单曲、随机 播放逻辑
音量控制 音量大小调节 系统接口

1.3 播放模式定义

序号 模式名称 Emoji 描述 特点
1 顺序播放 📋 按列表顺序依次播放 默认模式
2 列表循环 🔄 播放完毕后从头开始 循环播放
3 单曲循环 🔂 重复播放当前歌曲 单曲循环
4 随机播放 🔀 随机选择歌曲播放 随机播放

1.4 均衡器预设定义

序号 预设名称 Emoji 频段特点 适用场景
1 普通 🎵 平直频响 日常聆听
2 低音增强 🔊 低频提升 流行、电子
3 高音增强 🎤 高频提升 古典、人声
4 人声突出 👤 中频提升 人声歌曲
5 摇滚 🎸 高低频提升 摇滚音乐
6 爵士 🎷 中高频提升 爵士音乐
7 古典 🎻 整体均衡 古典音乐
8 电子 🎹 低高频提升 电子音乐

1.5 均衡器频段定义

序号 频段名称 频率范围 调节范围 影响描述
1 低频 60Hz -12dB ~ +12dB 低音力度
2 中低频 230Hz -12dB ~ +12dB 低音厚度
3 中频 910Hz -12dB ~ +12dB 人声清晰度
4 中高频 3.6kHz -12dB ~ +12dB 乐器明亮度
5 高频 14kHz -12dB ~ +12dB 高音通透感

1.6 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
音频播放 audioplayers >= 5.0.0
后台服务 audio_service >= 0.18.0
音频会话 audio_session >= 0.1.0
文件路径 path_provider >= 2.0.0
权限管理 permission_handler >= 11.0.0
目标平台 鸿蒙OS / Android / iOS API 21+

1.7 项目结构

lib/
└── main_music_player.dart
    ├── LocalMusicPlayerApp              # 应用入口
    ├── PlayMode                         # 播放模式枚举
    ├── EqualizerPreset                  # 均衡器预设枚举
    ├── MusicFile                        # 音乐文件模型
    ├── LyricLine                        # 歌词行模型
    ├── Playlist                         # 播放列表模型
    ├── MusicPlayerState                 # 播放器状态
    ├── MusicPlayerController            # 播放器控制器
    ├── MusicPlayerHomePage              # 主页面(底部导航)
    ├── _buildMusicListPage              # 音乐列表页
    ├── _buildPlaylistsPage              # 播放列表页
    ├── _buildEqualizerPage              # 均衡器页
    ├── _buildSettingsPage               # 设置页
    ├── _buildMiniPlayer                 # 迷你播放器
    └── _FullPlayerView                  # 全屏播放器

二、系统架构

2.1 整体架构图

Data Layer

Business Layer

Presentation Layer

主页面
MusicPlayerHomePage

音乐列表

播放列表

均衡器

设置

歌曲列表

搜索筛选

歌单管理

歌单详情

预设选择

自定义调节

播放设置

存储设置

播放器控制器
MusicPlayerController

音频引擎
AudioEngine

歌词解析器
LyricParser

均衡器管理器
EqualizerManager

MusicFile
音乐文件

Playlist
播放列表

LyricLine
歌词

EqualizerPreset
均衡器预设

2.2 类图设计

manages

contains

contains

contains

has

has

LocalMusicPlayerApp

+Widget build()

«enumeration»

PlayMode

+String label

+IconData icon

+sequence()

+loop()

+single()

+shuffle()

+next()

«enumeration»

EqualizerPreset

+String label

+List<double> gains

+normal()

+bass()

+treble()

+vocal()

+rock()

+jazz()

+classical()

+electronic()

MusicFile

+String id

+String title

+String artist

+String album

+String path

+int duration

+String? albumArt

+int playCount

+DateTime addedAt

+String durationText

+String displayTitle

LyricLine

+int timestamp

+String text

+String timeText

Playlist

+String id

+String name

+String? cover

+List<String> musicIds

+DateTime createdAt

+String description

+int count

MusicPlayerState

+List<MusicFile> musicList

+List<Playlist> playlists

+MusicFile? currentMusic

+bool isPlaying

+Duration currentPosition

+Duration totalDuration

+PlayMode playMode

+double volume

+EqualizerPreset equalizerPreset

+List<double> customEqualizerGains

+List<LyricLine> lyrics

+int currentLyricIndex

+bool showLyrics

+copyWith()

MusicPlayerController

-MusicPlayerState _state

-Timer? _progressTimer

+MusicPlayerState state

+initializeWithMockData()

+playMusic()

+togglePlayPause()

+playNext()

+playPrevious()

+seekTo()

+setPlayMode()

+setVolume()

+setEqualizerPreset()

+setCustomEqualizerGain()

2.3 页面导航流程

音乐

歌单

均衡器

设置

应用启动

主页面

底部导航

音乐列表页

播放列表页

均衡器页

设置页

点击歌曲

迷你播放器

全屏播放器

显示歌词

切换歌曲

调节进度

创建歌单

查看歌单详情

播放歌单

选择预设

自定义调节

播放设置

存储设置

2.4 播放流程

音频引擎 播放器控制器 主页 用户 音频引擎 播放器控制器 主页 用户 loop [播放过程] 选择歌曲 playMusic(music) 更新状态 加载音频 准备就绪 开始播放 显示播放界面 更新进度 更新歌词 显示进度和歌词 暂停/播放 暂停/继续 状态更新 更新界面 下一曲 获取下一首 加载新音频

三、核心模块设计

3.1 数据模型设计

3.1.1 播放模式枚举 (PlayMode)
enum PlayMode {
  sequence(label: '顺序播放', icon: Icons.list),
  loop(label: '列表循环', icon: Icons.repeat),
  single(label: '单曲循环', icon: Icons.repeat_one),
  shuffle(label: '随机播放', icon: Icons.shuffle);

  final String label;
  final IconData icon;
  const PlayMode({required this.label, required this.icon});

  PlayMode get next {
    final values = PlayMode.values;
    final index = values.indexOf(this);
    return values[(index + 1) % values.length];
  }
}
3.1.2 均衡器预设枚举 (EqualizerPreset)
enum EqualizerPreset {
  normal(label: '普通', gains: [0.0, 0.0, 0.0, 0.0, 0.0]),
  bass(label: '低音增强', gains: [6.0, 4.0, 0.0, -2.0, -4.0]),
  treble(label: '高音增强', gains: [-4.0, -2.0, 0.0, 4.0, 6.0]),
  vocal(label: '人声突出', gains: [-2.0, 0.0, 4.0, 4.0, 0.0]),
  rock(label: '摇滚', gains: [5.0, 3.0, -1.0, 2.0, 4.0]),
  jazz(label: '爵士', gains: [3.0, 1.0, 0.0, 2.0, 4.0]),
  classical(label: '古典', gains: [4.0, 3.0, -2.0, -2.0, 3.0]),
  electronic(label: '电子', gains: [4.0, 2.0, 0.0, -2.0, 5.0]);

  final String label;
  final List<double> gains;
  const EqualizerPreset({required this.label, required this.gains});
}
3.1.3 音乐文件模型 (MusicFile)
class MusicFile {
  final String id;
  final String title;
  final String artist;
  final String album;
  final String path;
  final int duration;
  final String? albumArt;
  final int playCount;
  final DateTime addedAt;

  const MusicFile({
    required this.id,
    required this.title,
    required this.artist,
    required this.album,
    required this.path,
    required this.duration,
    this.albumArt,
    this.playCount = 0,
    required this.addedAt,
  });

  String get durationText {
    final minutes = duration ~/ 60;
    final seconds = duration % 60;
    return '$minutes:${seconds.toString().padLeft(2, '0')}';
  }

  String get displayTitle => title.isEmpty ? path.split('/').last : title;
}
3.1.4 播放列表模型 (Playlist)
class Playlist {
  final String id;
  final String name;
  final String? cover;
  final List<String> musicIds;
  final DateTime createdAt;
  final String description;

  const Playlist({
    required this.id,
    required this.name,
    this.cover,
    required this.musicIds,
    required this.createdAt,
    this.description = '',
  });

  int get count => musicIds.length;
}
3.1.5 音乐播放分布
35% 30% 25% 10% 音乐播放模式使用分布示例 顺序播放 列表循环 随机播放 单曲循环

3.2 页面结构设计

3.2.1 主页面布局

MusicPlayerHomePage

IndexedStack

音乐列表页

播放列表页

均衡器页

设置页

迷你播放器

NavigationBar

歌曲信息

播放控制

音乐 Tab

歌单 Tab

均衡器 Tab

设置 Tab

3.2.2 音乐列表页结构

音乐列表页

SliverAppBar

歌曲列表

渐变背景

歌曲统计

搜索按钮

排序按钮

歌曲项

封面图

标题

艺术家

时长

更多选项

3.2.3 全屏播放器结构

全屏播放器

顶部栏

中间区域

进度区域

控制区域

底部操作

下拉关闭

歌曲标题

更多选项

专辑封面

歌词显示

进度条

时间显示

播放模式

上一曲

播放/暂停

下一曲

歌词切换

3.2.4 均衡器页结构

均衡器页

SliverAppBar

预设选择

自定义调节

音量控制

预设标签组

频段滑块

60Hz

230Hz

910Hz

3.6kHz

14kHz

3.3 播放器控制器逻辑

播放歌曲

暂停/播放

上一曲/下一曲

调节进度

切换模式

调节均衡器

初始化

加载音乐列表

加载播放列表

用户操作

操作类型

设置当前歌曲

切换播放状态

切换歌曲

更新进度

更新播放模式

更新均衡器

启动进度定时器

是否播放

停止定时器

更新进度

更新歌词索引

是否结束

播放下一曲

3.4 歌词同步逻辑

匹配

不匹配

加载歌词

解析LRC格式

生成歌词列表

播放开始

定时更新

获取当前时间

遍历歌词列表

时间匹配

更新当前歌词索引

继续遍历

高亮显示歌词

滚动到当前行

播放继续?

结束


四、UI设计规范

4.1 配色方案

应用以活力四射的粉红色为主色调,象征音乐的热情与活力:

颜色类型 色值 用途
主色 #E91E63 (Pink) 导航、主题元素
辅助色 #F48FB1 渐变效果
第三色 #F8BBD9 卡片背景
强调色 #EC407A 按钮高亮
背景色 #FAFAFA 页面背景
卡片背景 #FFFFFF 信息卡片
播放色 #4CAF50 播放状态
暂停色 #FF9800 暂停状态

4.2 播放模式配色

模式 色值 视觉效果
顺序播放 #2196F3 蓝色
列表循环 #4CAF50 绿色
单曲循环 #FF9800 橙色
随机播放 #9C27B0 紫色

4.3 字体规范

元素 字号 字重 颜色
页面标题 24px Bold 主色
歌曲标题 18px Bold #000000
艺术家名 14px Regular #666666
歌词文字 16px Regular #333333
当前歌词 20px Bold 主色
时间显示 14px Regular #999999

4.4 组件规范

4.4.1 迷你播放器
┌─────────────────────────────────────┐
│  ┌────┐  歌曲名称                    │
│  │ 🎵 │  艺术家名     ◀ ▶ ⏭        │
│  └────┘                             │
└─────────────────────────────────────┘
4.4.2 歌曲列表项
┌─────────────────────────────────────┐
│  ┌────┐  歌曲标题                    │
│  │ 🎵 │  艺术家 · 专辑    3:45  ⋮   │
│  └────┘                             │
└─────────────────────────────────────┘
4.4.3 全屏播放器
┌─────────────────────────────────────┐
│  ∨              正在播放         ⋮  │
│                                     │
│         ┌───────────────┐          │
│         │               │          │
│         │      🎵       │          │
│         │               │          │
│         └───────────────┘          │
│                                     │
│           歌曲标题                   │
│           艺术家名                   │
│                                     │
│  ────────────●────────────────      │
│  1:23                    3:45      │
│                                     │
│    🔀    ⏮    ▶    ⏭    🎤        │
│                                     │
│    ❤️    📋    ↗️    ⬇️             │
└─────────────────────────────────────┘
4.4.4 均衡器界面
┌─────────────────────────────────────┐
│  预设模式                            │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐   │
│  │普通 │ │低音 │ │高音 │ │人声 │   │
│  └─────┘ └─────┘ └─────┘ └─────┘   │
│                                     │
│  自定义调节                          │
│  ┌─────────────────────────────┐   │
│  │   ▲    ▲    ▲    ▲    ▲    │   │
│  │   │    │    │    │    │    │   │
│  │   │    │    │    │    │    │   │
│  │ 60Hz 230Hz 910Hz 3.6kHz 14kHz│   │
│  └─────────────────────────────┘   │
└─────────────────────────────────────┘
4.4.5 歌词显示
┌─────────────────────────────────────┐
│            歌词显示                  │
│                                     │
│        窗外的麻雀 在电线杆上多嘴      │
│        你说这一句 很有夏天的感觉      │
│      ★ 手中的铅笔 在纸上来来回回 ★   │
│        我用几行字形容你是我的谁      │
│        秋刀鱼的滋味 猫跟你都想了解    │
│                                     │
└─────────────────────────────────────┘

五、核心功能实现

5.1 播放器控制器实现

class MusicPlayerController extends ChangeNotifier {
  MusicPlayerState _state = const MusicPlayerState();
  Timer? _progressTimer;

  MusicPlayerState get state => _state;

  void playMusic(MusicFile music) {
    _state = _state.copyWith(
      currentMusic: music,
      isPlaying: true,
      currentPosition: Duration.zero,
      totalDuration: Duration(seconds: music.duration),
      lyrics: _generateMockLyrics(music),
      currentLyricIndex: 0,
    );
    _startProgressTimer();
    notifyListeners();
  }

  void togglePlayPause() {
    if (_state.currentMusic == null) return;
    _state = _state.copyWith(isPlaying: !_state.isPlaying);
    if (_state.isPlaying) {
      _startProgressTimer();
    } else {
      _stopProgressTimer();
    }
    notifyListeners();
  }

  void playNext() {
    if (_state.musicList.isEmpty) return;
    int nextIndex;
    switch (_state.playMode) {
      case PlayMode.sequence:
        nextIndex = (_state.currentIndex + 1) % _state.musicList.length;
        break;
      case PlayMode.loop:
        nextIndex = (_state.currentIndex + 1) % _state.musicList.length;
        break;
      case PlayMode.single:
        nextIndex = _state.currentIndex;
        break;
      case PlayMode.shuffle:
        nextIndex = _random.nextInt(_state.musicList.length);
        break;
    }
    if (nextIndex >= 0 && nextIndex < _state.musicList.length) {
      playMusic(_state.musicList[nextIndex]);
    }
  }

  void seekTo(Duration position) {
    _state = _state.copyWith(currentPosition: position);
    _updateLyricIndex();
    notifyListeners();
  }
}

5.2 均衡器管理实现

void setEqualizerPreset(EqualizerPreset preset) {
  _state = _state.copyWith(
    equalizerPreset: preset,
    customEqualizerGains: List.from(preset.gains),
  );
  notifyListeners();
}

void setCustomEqualizerGain(int band, double gain) {
  final newGains = List<double>.from(_state.customEqualizerGains);
  if (band >= 0 && band < newGains.length) {
    newGains[band] = gain.clamp(-12.0, 12.0);
  }
  _state = _state.copyWith(customEqualizerGains: newGains);
  notifyListeners();
}

5.3 歌词同步实现

void _updateLyricIndex() {
  final currentMs = _state.currentPosition.inMilliseconds;
  int newIndex = -1;
  for (int i = 0; i < _state.lyrics.length; i++) {
    if (_state.lyrics[i].timestamp <= currentMs) {
      newIndex = i;
    } else {
      break;
    }
  }
  if (newIndex != _state.currentLyricIndex) {
    _state = _state.copyWith(currentLyricIndex: newIndex);
  }
}

5.4 播放列表管理实现

void addToPlaylist(String playlistId, String musicId) {
  final index = _state.playlists.indexWhere((p) => p.id == playlistId);
  if (index == -1) return;
  final playlist = _state.playlists[index];
  if (playlist.musicIds.contains(musicId)) return;
  final newPlaylists = List<Playlist>.from(_state.playlists);
  newPlaylists[index] = Playlist(
    id: playlist.id,
    name: playlist.name,
    cover: playlist.cover,
    musicIds: [...playlist.musicIds, musicId],
    createdAt: playlist.createdAt,
    description: playlist.description,
  );
  _state = _state.copyWith(playlists: newPlaylists);
  notifyListeners();
}

void createPlaylist(String name, String description) {
  final newPlaylist = Playlist(
    id: 'playlist_${DateTime.now().millisecondsSinceEpoch}',
    name: name,
    musicIds: [],
    createdAt: DateTime.now(),
    description: description,
  );
  _state = _state.copyWith(playlists: [..._state.playlists, newPlaylist]);
  notifyListeners();
}

5.5 进度更新实现

void _startProgressTimer() {
  _stopProgressTimer();
  _progressTimer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
    if (!_state.isPlaying) return;
    final newPosition = _state.currentPosition + const Duration(milliseconds: 100);
    if (newPosition >= _state.totalDuration) {
      playNext();
    } else {
      _state = _state.copyWith(currentPosition: newPosition);
      _updateLyricIndex();
      notifyListeners();
    }
  });
}

void _stopProgressTimer() {
  _progressTimer?.cancel();
  _progressTimer = null;
}

六、交互设计

6.1 播放流程

全屏播放器 迷你播放器 播放器控制器 音乐列表 用户 全屏播放器 迷你播放器 播放器控制器 音乐列表 用户 loop [播放过程] 浏览歌曲 显示歌曲列表 点击歌曲 playMusic(music) 更新状态 显示播放信息 点击展开 显示全屏 显示播放界面 更新进度 显示进度和歌词 切换歌曲 playNext/playPrevious 更新歌曲

6.2 均衡器调节流程

预设模式

自定义调节

打开均衡器

显示当前设置

选择调节方式

选择预设

应用预设值

更新音频输出

拖动滑块

实时更新增益值

保存设置

6.3 歌单管理流程

点击创建

弹出对话框

确认创建

点击歌单

选择歌曲

点击播放

查看歌单列表

创建歌单

输入信息

保存歌单

查看歌单详情

添加歌曲

播放歌单

播放中


七、扩展功能规划

7.1 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 基础UI框架 播放器核心 均衡器实现 歌词同步 播放列表管理 后台播放服务 音乐扫描优化 主题定制 睡眠定时 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 本地音乐播放器开发计划

7.2 功能扩展建议

7.2.1 音乐扫描优化

扫描功能:

  • 智能识别音乐文件
  • 自动获取歌曲信息
  • 专辑封面提取
  • 歌词自动匹配
7.2.2 主题定制

主题功能:

  • 多种主题颜色选择
  • 深色/浅色模式
  • 自定义背景图片
  • 动态主题效果
7.2.3 高级播放功能

播放功能:

  • 淡入淡出效果
  • 无缝播放
  • 变速播放
  • AB段循环

八、注意事项

8.1 开发注意事项

  1. 音频权限:确保申请存储权限和音频权限

  2. 后台播放:正确配置后台服务,避免被系统杀死

  3. 音频焦点:正确处理音频焦点,与其他应用协调

  4. 电量优化:优化播放逻辑,减少电量消耗

  5. 存储访问:适配不同版本的存储权限策略

8.2 常见问题

问题 原因 解决方案
无法扫描音乐 权限未授予 申请存储权限
后台播放中断 服务被杀死 配置前台服务
歌词不同步 时间戳解析错误 优化LRC解析
均衡器无效 音频处理未启用 检查音频配置
播放卡顿 文件读取慢 使用缓冲机制

8.3 使用技巧

🎵 音乐播放器使用技巧 🎵

播放控制

  • 双击歌曲快速播放
  • 长按歌曲显示选项
  • 左滑歌曲添加到歌单
  • 右滑歌曲从列表移除

均衡器调节

  • 选择预设快速调整
  • 自定义滑块精细调节
  • 保存个人偏好设置
  • 不同耳机适配不同预设

歌单管理

  • 创建主题歌单分类
  • 批量添加歌曲
  • 智能歌单推荐
  • 歌单导出分享

九、鸿蒙适配说明

9.1 权限配置

ohos/entry/src/main/module.json5 中添加权限:

{
  "module": {
    "requestPermissions": [
      {"name": "ohos.permission.INTERNET"},
      {"name": "ohos.permission.READ_MEDIA"},
      {"name": "ohos.permission.WRITE_MEDIA"},
      {"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"}
    ]
  }
}

9.2 第三方库适配状态

第三方库 适配状态 说明
audioplayers ✅ 已适配 音频播放核心库
audio_service ✅ 已适配 后台播放服务
audio_session ✅ 已适配 音频会话管理
path_provider ✅ 已适配 文件路径获取
permission_handler ✅ 已适配 权限管理
shared_preferences ✅ 已适配 数据存储

9.3 运行命令

# 查看可用设备
flutter devices

# 运行到Web服务器
flutter run -d web-server -t lib/main_music_player.dart --web-port 8145

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 -t lib/main_music_player.dart

# 代码分析
flutter analyze lib/main_music_player.dart

十、总结

本地音乐播放器应用为用户提供了一套完整的音乐播放解决方案。应用支持扫描设备本地音乐文件,提供播放列表管理、歌词显示、均衡器调节等功能,支持后台播放,让用户随时随地享受高品质音乐。

核心功能涵盖音乐扫描、播放控制、歌词显示、均衡器调节、播放列表、后台播放、播放模式、音量控制八大模块。用户可以浏览本地音乐、创建个性化歌单、调节音效、管理播放设置,打造专属的音乐空间。

应用采用 Material Design 3 设计规范,以活力四射的粉红色为主色调,象征音乐的热情与活力。通过本应用,希望能够为用户带来纯净、流畅的音乐聆听体验,让音乐成为生活的一部分。

本地音乐播放器——聆听属于你的音乐


Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐