使用Flutter或Python访问用户设备音频文件及元数据的实现方案问询
Flutter端实现方案
前置准备
首先需要申请设备存储/媒体访问权限,使用permission_handler包实现权限申请逻辑:
- 安卓端:安卓13及以上需申请
READ_MEDIA_AUDIO权限,更低版本需申请READ_EXTERNAL_STORAGE权限 - iOS端:需申请媒体库访问权限,需在Info.plist中添加
NSAppleMusicUsageDescription权限说明
核心实现
推荐使用on_audio_query包完成音频扫描和元数据读取,该包同时支持安卓、iOS平台,默认兼容mp3、wav等主流音频格式:
- 先在pubspec.yaml中添加依赖:
dependencies: permission_handler: ^11.0.1 on_audio_query: ^2.9.0
- 权限申请代码示例:
import 'dart:io'; import 'package:permission_handler/permission_handler.dart'; import 'package:device_info_plus/device_info_plus.dart'; Future<bool> checkAndRequestAudioPermission() async { if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt >= 33) { return await Permission.audio.request().isGranted; } else { return await Permission.storage.request().isGranted; } } else if (Platform.isIOS) { return await Permission.mediaLibrary.request().isGranted; } return false; }
- 扫描音频并读取元数据代码示例:
import 'package:on_audio_query/on_audio_query.dart'; final OnAudioQuery audioQuery = OnAudioQuery(); Future<List<SongModel>> getTargetAudioFiles() async { // 查询设备所有音频文件 List<SongModel> allSongs = await audioQuery.querySongs( sortType: SongSortType.TITLE, orderType: OrderType.ASC_OR_SMALLER, uriType: UriType.EXTERNAL, ignoreCase: true, ); // 过滤仅保留mp3、wav格式文件 return allSongs.where((song) { final ext = song.fileExtension.toLowerCase(); return ext == 'mp3' || ext == 'wav'; }).toList(); }
返回的SongModel对象可直接读取所需元数据:
- 歌曲名:
song.title - 作者名:
song.artist - 专辑名:
song.album - 音频时长:
song.duration - 本地文件路径:
song.data
Python端备选实现方案
如果需要离线预处理音频文件,可使用以下方案实现本地音频扫描和元数据读取:
- 安装依赖:
pip install mutagen - 实现代码:
import os from mutagen import File def scan_local_audio(root_dir: str) -> list[dict]: audio_result = [] for root, _, files in os.walk(root_dir): for file in files: file_ext = os.path.splitext(file)[-1].lower() if file_ext not in ('.mp3', '.wav'): continue file_path = os.path.join(root, file) try: audio = File(file_path, easy=True) if not audio: continue audio_meta = { "file_path": file_path, "title": audio.get("title", [os.path.splitext(file)[0]])[0], "artist": audio.get("artist", ["未知作者"])[0], "album": audio.get("album", ["未知专辑"])[0], "duration": round(audio.info.length, 2) if hasattr(audio, "info") else 0 } audio_result.append(audio_meta) except Exception: # 跳过损坏的音频文件 continue return audio_result
调用时传入待扫描的根目录路径,即可返回所有符合要求的音频文件及其元数据。
内容的提问来源于stack exchange,提问作者user15887518
相关产品推荐
相关产品推荐

