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

Flutter中audioplayers无法通过URL播放音频问题求助

问题:使用audioplayers播放PHP本地服务器音频URL失败

我正在开发一款音乐播放器应用,计划从PHP本地服务器获取音频URL进行播放。使用的包为audioplayers,该包支持播放应用内资源或通过URL播放音频。播放本地资源时一切正常,但通过URL播放时无法正常工作,出现了Source Set异常。

Source Set 异常

相关代码

import 'dart:ui';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:tahween/api/linkAPI.dart';
class MusicPlayer extends StatefulWidget{
  const MusicPlayer({super.key});
  @override
  State<StatefulWidget> createState() =>MusicPlayerState();
}
class MusicPlayerState extends State<MusicPlayer> {
    final audioPlayer = AudioPlayer();
    Duration duration = Duration.zero;
    Duration position = Duration.zero;
    bool isPlaying = false;
    IconData playIcon = Icons.play_arrow;
  @override
  void initState() {
            super.initState();
    audioPlayer.onPlayerStateChanged.listen((state) {
      setState(() {
      isPlaying = state ==PlayerState.playing;
      playIcon = playIcon==Icons.play_arrow?Icons.pause:Icons.play_arrow;
      });
    });
    audioPlayer.onDurationChanged.listen((newDuration) {
      setState(() {
        duration=newDuration;
      });
    });
  audioPlayer.onPositionChanged.listen((newPosition) {
    setState(() {
      position=newPosition;
    });
    });
    print("ready");
      }
  @override
  Widget build(BuildContext context) {

    double screenHeight = MediaQuery.of(context).size.height;
    double screenWidth = MediaQuery.of(context).size.width;
    return Scaffold(
      body: Stack(
        children: [
          SizedBox(
            height: screenHeight,
            width: screenWidth,
            child: Image.asset(
              "lib/images/music player.jpg", // Original clear image
              fit: BoxFit.fill,
            ),
          ),
          Positioned.fill(
            child: BackdropFilter(
              filter: ImageFilter.blur(
                  sigmaX: 10.0,
                  sigmaY: 10.0), // Adjust blur intensity as needed
              child: Container(
                color:
                    Colors.black.withOpacity(0.5), // Adjust opacity as needed
              ),
            ),
          ),
          Positioned(
            top: screenHeight / 10,
            left: screenWidth / 10,
            right: screenWidth / 10,
            child: Column(
              children: [
                SizedBox(
                  height: screenHeight / 2,
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(
                        30.0), 
                    child: Image.asset("lib/images/music player.jpg",
                        fit: BoxFit.fill),
                  ),
                ),
                SizedBox(
                  height: screenHeight / 20,
                ),
                SliderTheme(
                  data: SliderTheme.of(context).copyWith(
                    activeTrackColor: Colors.white,
                    thumbColor: Colors.white,
                    inactiveTrackColor: Colors.black
                  ),
                  child: Slider(
                    value: position.inSeconds.toDouble(),
                    min: 0,
                    max: duration.inSeconds.toDouble(),
                    onChanged: (value) async{
                      final position = Duration(seconds: value.toInt());
                      await audioPlayer.seek(position);
                      await audioPlayer.resume();
                      
                    },),
                ),
                SizedBox(
                  height: screenHeight / 20,
                ),
                Row(
                  //control buttons
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    IconButton(
                        onPressed: () {},
                        icon: Icon(CupertinoIcons.shuffle,color: Colors.grey[500],)),
                    ElevatedButton(
                        onPressed: () {},
                        child: const Icon(
                          CupertinoIcons.backward_end_alt_fill,
                          color: Colors.black,
                        )),
                    InkWell(
                        onTap: (){
                        if(isPlaying){
                          print("pause");
                           audioPlayer.pause();
                        } else{
                          // https://youtu.be/TvUvq2SnTtA
                          Source src= UrlSource(musicURL);
                          audioPlayer.play(src);
                          print("play");
                        }
                      },
                      child: Container(
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(100),
                          color: Colors.black,
                        ),
                        height: screenWidth / 7,
                        width: screenWidth / 7,
                        child: Icon(
                          playIcon,
                          color: Colors.white,
                        ),
                      ),
                    ),
                    ElevatedButton(
                        onPressed: () {},
                        child: const Icon(
                          CupertinoIcons.forward_end_alt_fill,
                          color: Colors.black,
                        )),
                    IconButton(onPressed: () {}, icon: Icon(Icons.repeat, color: Colors.grey[500],))
                  ],
                ),
                SizedBox(
                  height: screenHeight / 20,
                ),
                const Text(
                  "Song name",
                  style: TextStyle(
                      color: Colors.white,
                      fontSize: 30,
                      fontWeight: FontWeight.bold),
                ),
                const Text(
                  "Don't forget to close your eyes!",
                  style: TextStyle(
                      color: Colors.white,
                      fontSize: 17,
                      fontWeight: FontWeight.bold),
                ),
                const Text(
                  "Duration",
                  style: TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}

排查与解决步骤

  • 验证URL有效性
    确认musicURL是完整可访问的HTTP/HTTPS链接(如http://localhost:8000/audio/song.mp3),直接在浏览器访问该链接,检查是否能正常加载音频,排除服务器端路径或文件存在性问题。

  • 处理服务器权限与跨域

    • 给PHP服务器的音频文件设置正确读取权限,确保服务器能访问该文件
    • 若出现跨域问题,在PHP接口中添加CORS响应头:
      header("Access-Control-Allow-Origin: *");
      header("Access-Control-Allow-Methods: GET");
      
  • 调整audioplayers配置

    • 升级到最新版本的audioplayers,避免版本兼容bug
    • 播放时显式指定模式(针对Android):
      audioPlayer.play(src, mode: PlayerMode.mediaPlayer);
      
  • 添加异常捕获
    在播放逻辑中加入错误捕获,打印具体异常信息:

    try {
      Source src = UrlSource(musicURL);
      await audioPlayer.play(src);
      print("播放成功");
    } catch (e) {
      print("播放错误详情: $e");
    }
    
  • 平台权限配置

    • Android:在AndroidManifest.xml中添加网络权限,若使用HTTP链接(非HTTPS),需开启明文流量:
      <uses-permission android:name="android.permission.INTERNET" />
      <application ... android:usesCleartextTraffic="true">
      
    • iOS:在Info.plist中添加允许任意网络加载的配置:
      <key>NSAppTransportSecurity</key>
      <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
      </dict>
      

内容的提问来源于stack exchange,提问作者Sharaf Shaheen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 22:55:42