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

Flutter登录页背景视频播放报错:ExoPlaybackException: Source error

问题:Flutter中使用VideoPlayerController.asset加载本地视频失败

开发带背景视频的登录页时,通过VideoPlayerController.asset初始化、加载并播放视频时出现播放错误,错误日志如下:

I/ExoPlayerImpl( 1409): Release 3fa0f6d [ExoPlayerLib/2.18.1] [emu64x, sdk_gphone64_x86_64, Google, 33] [goog.exo.core, goog.exo.exoplayer, goog.exo.decoder, goog.exo.datasource]
I/ExoPlayerImpl( 1409): Init 2f7c84d [ExoPlayerLib/2.18.1] [emu64x, sdk_gphone64_x86_64, Google, 33]
D/EGL_emulation( 1409): app_time_stats: avg=8839.84ms min=8839.84ms max=8839.84ms count=1
E/ExoPlayerImplInternal( 1409): Playback error
E/ExoPlayerImplInternal( 1409):   com.google.android.exoplayer2.ExoPlaybackException: Source error
E/ExoPlayerImplInternal( 1409):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:632)
E/ExoPlayerImplInternal( 1409):       at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:604)
E/ExoPlayerImplInternal( 1409):       at android.os.Handler.dispatchMessage(Handler.java:102)
E/ExoPlayerImplInternal( 1409):       at android.os.Looper.loopOnce(Looper.java:201)
E/ExoPlayerImplInternal( 1409):       at android.os.Looper.loop(Looper.java:288)
E/ExoPlayerImplInternal( 1409):       at android.os.HandlerThread.run(HandlerThread.java:67)
E/ExoPlayerImplInternal( 1409):   Caused by: com.google.android.exoplayer2.upstream.AssetDataSource$AssetDataSourceException: java.io.FileNotFoundException: flutter_assets/violet2.mp4
E/ExoPlayerImplInternal( 1409):       at com.google.android.exoplayer2.upstream.AssetDataSource.open(AssetDataSource.java:110)
E/ExoPlayerImplInternal( 1409):       at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:258)
E/ExoPlayerImplInternal( 1409):       at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
E/ExoPlayerImplInternal( 1409):       at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1005)
E/ExoPlayerImplInternal( 1409):       at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:412)
E/ExoPlayerImplInternal( 1409):       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
E/ExoPlayerImplInternal( 1409):       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
E/ExoPlayerImplInternal( 1409):       at java.lang.Thread.run(Thread.java:1012)
E/ExoPlayerImplInternal( 1409):   Caused by: java.io.FileNotFoundException: flutter_assets/violet2.mp4
E/ExoPlayerImplInternal( 1409):       at android.content.res.AssetManager.nativeOpenAsset(Native Method)
E/ExoPlayerImplInternal( 1409):       at android.content.res.AssetManager.open(AssetManager.java:904)
E/ExoPlayerImplInternal( 1409):       at com.google.android.exoplayer2.upstream.AssetDataSource.open(AssetDataSource.java:84)
E/ExoPlayerImplInternal( 1409):       ... 7 more
E/flutter ( 1409): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(VideoError, Video player had error com.google.android.exoplayer2.ExoPlaybackException: Source error, null, null)
E/flutter ( 1409): 
D/EGL_emulation( 1409): app_time_stats: avg=1372.88ms min=278.15ms max=2467.62ms count=2

实现代码如下:

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';

class WelcomeScreen extends StatefulWidget {
  const WelcomeScreen({Key? key}) : super(key: key);

  @override
  State<WelcomeScreen> createState() => _WelcomeScreenState();
}

class _WelcomeScreenState extends State<WelcomeScreen> {
  late VideoPlayerController _controller;
  bool _visible = false;

  @override
  void initState(){
   super.initState();

   SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp,]);

   final video = 'violet2.mp4';
   _controller = VideoPlayerController.asset(video);
   _controller.addListener(() => setState(() {}));
   _controller.initialize().then((_) {
     _controller.setLooping(true);
      Timer(const Duration(milliseconds: 100), () {
       setState(() {
         _controller.play();
         _visible = true;
       });
     });
   });
  }

  @override
  void dispose() {
    super.dispose();
    if (_controller != null) {
      _controller.dispose();
    }
  }

  _getVideoBackground() {
    return AnimatedOpacity(
      opacity: _visible ? 1.0 : 0.0,
      duration: const Duration(milliseconds: 1000),
      child: VideoPlayer(_controller),
    );
  }

  _getBackgroundColor() {
    return Container(
      color: Colors.white.withAlpha(120),
    );
  }

  _getNextButton() {
    return <Widget> [
      Container(
          alignment: Alignment.center,
          child: IconButton(
              onPressed: () {
            Navigator.pushNamed(context, 'login_screen');
            _controller.dispose();
          },
              style: ElevatedButton.styleFrom(
                backgroundColor: Colors.white,
          ),
              icon: Icon(Icons.arrow_forward)
          )
      )
    ];
  }

  _getContent() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisAlignment: MainAxisAlignment.start,
      children: <Widget>[
        Spacer(),
        ..._getNextButton()
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Stack(
          children: <Widget>[
            _getVideoBackground(),
            _getBackgroundColor(),
            _getContent(),
          ],
        ),
      ),
    );
  }
}

解决方案

从错误日志来看,核心问题是java.io.FileNotFoundException: flutter_assets/violet2.mp4,即无法找到指定的视频资源文件,按以下步骤排查修复:

1. 校验资源路径与pubspec.yaml配置

  • 文件位置:确认violet2.mp4的实际存放路径。如果放在项目根目录的assets文件夹下,初始化路径应改为'assets/violet2.mp4';若放在子文件夹(如assets/videos/),路径需对应为'assets/videos/violet2.mp4'。
  • pubspec声明:必须在pubspec.yaml中正确注册该资源,示例配置:
    flutter:
      assets:
        - assets/violet2.mp4
        # 若需加载文件夹下所有文件,可写:- assets/videos/
    
  • 刷新资源:执行flutter pub get命令,然后重启应用(热重载无法加载新添加的资源)。

2. 添加初始化错误捕获

在初始化视频控制器时加入错误处理,避免未处理异常导致崩溃:

@override
void initState(){
 super.initState();

 SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp,]);

 // 修正路径为正确的资源路径
 final video = 'assets/violet2.mp4';
 _controller = VideoPlayerController.asset(video);
 _controller.addListener(() => setState(() {}));
 _controller.initialize().then((_) {
   _controller.setLooping(true);
    Timer(const Duration(milliseconds: 100), () {
     setState(() {
       _controller.play();
       _visible = true;
     });
   });
 }).catchError((error) {
   print('视频初始化失败: $error');
   // 可在此处显示错误提示或切换为静态背景
 });
}

3. 优化代码细节

  • dispose方法:由于_controller用late声明,无需判空,直接调用dispose即可:
    @override
    void dispose() {
      _controller.dispose();
      super.dispose();
    }
    
  • 视频格式兼容性:确保视频为ExoPlayer支持的格式(推荐MP4+H.264编码),避免使用不兼容的视频文件。
  • 文件完整性:测试替换一个已知可用的视频文件,排除原文件损坏的可能。

内容的提问来源于stack exchange,提问作者Michele Sciacovelli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 05:55:05