Flutter视频播放器,简洁!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter视频播放器,简洁!相关的知识,希望对你有一定的参考价值。

参考技术A

注:亮度调节和音量调节gif无法体现,功能是ok的,其次默认Icon锁的close和open实在难以分辨。

环境:Flutter 2.8.1 channel stable ;Dart 2.15.1

需要音频播放器的看这里: Flutter音乐播放器

重点说下这个工具类,因为视频播放,涉及到状态改变有很多,笔者刚开始选择使用 InheritedWidget 来在众多的widget之间共享数据。但是总感觉这样有点繁琐,且不很优雅!

这里非广告,如果是使用 GetX 就很简单了,笔者也使用了 GetX 进行封装了,一泻千里的赶脚!,但是笔者还是那句话:刚开始接触Flutter的开发者不是很建议使用 GetX ,可以先熟悉下Flutter状态管理的基础原理再行使用。而且为了尽量简洁,还是不引入其他的第三方了。

我们选择对第三方插件进行封装的目的不外乎这几个:

于是笔者就写了一个工具类 VideoPlayerUtils ,专门且只用来处理播放器的所有业务。包括暂停、播放、跳转、调节音量、调节亮度、切换视频等操作。在所有的widget中不会引用关于 video_player 或其他第三方插件的任何信息, VideoPlayerUtils 负责widget与播放器之间的所有操作交互。后续优化迭代或更换播放器插件时,只需针对这个工具类进行修改,对所有widget不会有任何的影响,大大的解耦合了。

其中 VideoPlayerState :

提供以上的公共属性,可以通过 VideoPlayerUtils 来获取对应的值,使用 get 只读,使外界不会误修改这些属性,以保证数值的安全性。开发者可根据自身需要自行添加属性。

提供以上方法来处理播放器的所有业务。同样的开发者可根据自身需要自行添加或修改。

重点说下这个方法,是整个业务的核心方法,控制视频的播放或暂停。开发者只要遇到播放或暂停是均可调用此方法,具体是播放或暂停,内部根据传入的 url 自行判断,开发者不需要关心。

切换新视频也是使用此方法,传入的 url 与上次不一致,自动切换新视频。笔者可根据 statusListener 来监听播放状态的改变,以此处理自身逻辑。

这个也需要提下,视频播放器在播放新视频时会异步初始化,一般我们的操作是在 initState() 初始化,成功后再 setState() 。这里笔者遇到一个让人蛋疼的问题:

我们看 video_player 的使用:

VideoPlayer(controller) :widget中已经持有了controller。本来笔者封装的目的就是为了让widget与controller的之间解耦合。但此时的笔者。。。。

放弃不是不可能放弃的,这辈子都不会放弃的!

于是笔者取了巧,写了一个初始化监听器 initializedListener ,包换2个参数: bool,Widget ,初始化是否成功;其中widget为初始化成功返回需要展示的播放器UI,失败默认返回 const SizedBox() 。

到这里就可以简单使用了:

没看错,视频播放就是这么简单。

如果有更多的业务功能,笔者也按照自己的需求写了一套,同样的开发者可根据自身需要自行添加或修改。

VideoPlayerGestures 主要是处理手势的,比如快进、快退等跳转播放;左侧上下滑动调节亮度;右侧上下滑动调节音量;单击是否开启沉浸式播放,所有widget的隐藏与显示;双击播放、暂停等。

哦,还有 PercentageWidget 也放到这个文件下了,就是这玩意:

因为显示的百分比与手势相关,随着手势移动而更新。开发者可自行处理。

笔者处出于简单考虑,就按照整个UI的位置命名了。瞅一眼就知道是啥玩意。

同样的开发者可根据自身需要自行添加或修改。

就是这玩意:

同样的开发者可根据自身需要自行添加或修改。话说这个锁的 Icon 的open和close是真的难分辨!

就是这玩意:

同样的开发者可根据自身需要自行添加或修改。

这玩意是自定义的,别问,问就是跟产品干一架落了下风

主要就是自定义这玩意:

同样的开发者可根据自身需要自定义。

注:这里没有添加缓冲的进度,开发可查看 video_player 中的源码 VideoProgressIndicator ,按业务自行定义。

这玩意就是整合以上的widget,再考虑下全屏的安全区域,没啥东西。开发者可自行处理!

具体的实现监听器的思路, 看这里 。

自此一个漂亮的Flutter视频播放器就已经结束了。如果您觉得对您有些许帮助的话,欢迎 Star

Flutter WebView 插件无法播放某些 YouTube 视频

【中文标题】Flutter WebView 插件无法播放某些 YouTube 视频【英文标题】:Flutter WebView plugin unable to play some YouTube videos 【发布时间】:2019-10-14 08:33:33 【问题描述】:

webview_flutter 插件无法播放某些 YouTube 嵌入视频,这些视频如果在网络应用中播放则可以正常工作。视频显示“视频不可用”。在 Flutter 应用中内联播放 YouTube 视频已成为问题至少一年了。

https://github.com/flutter/flutter/issues/13756

我尝试了各种 Flutter 插件来内联播放 YouTube 视频,但它们要么只支持 Android,要么不支持 YouTube。

我尝试在 WebView 插件中直接使用 HTML 字符串(YouTube iframe),但视频不可用。从网络服务器加载 HTML 允许播放一些视频,否则这些视频不会直接在颤振应用程序中播放,例如一些音乐视频显示“视频不可用。该视频包含来自 Vevo 的内容,该视频已阻止其在网站或应用程序上显示”。

但是,如果我使用 YouTube iframe API(请参阅代码)从 Web 应用程序启动相同的视频,它可以正常工作,即嵌入未被禁用,但这些视频无法在 Flutter 应用程序中播放。我还阅读了在 Android 中播放 YouTube 视频的类似问题,建议使用 WebChromeClient,这在 Flutter 中不可用。

在 WebView 插件中显示 YouTube 视频的 Flutter 应用。

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

// Use IP instead of localhost to access local webserver
const _youTubeUrl = 'http://localhost:8080';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'YouTube Video',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'YouTube Video'),
    );
  


class MyHomePage extends StatefulWidget 
  final String title;

  MyHomePage(Key key, this.title) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  WebViewController _controller;

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: WebView(
              initialUrl: '$_youTubeUrl/videos/IyFZznAk69U',
              javascriptMode: JavascriptMode.unrestricted,
              onWebViewCreated: (WebViewController controller) =>
                  _controller = controller,
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.play_arrow),
        onPressed: () async 
          await _controller.evaluateJavascript('player.loadVideoById("d_m5csmrf7I")');
        ,
      ),
    );
  

通过快速路由返回 index.html 的 Node.js 服务器端代码

const path = require("path");
const express = require("express");

const server = express();

// Define route
api.get("/", (req, res) =>
  res.sendFile(path.join(__dirname + "/index.html"))
);

const port = process.env.PORT || 8080;

server.listen(port, () => console.log(`Server listening on $port`));

process.on("exit", () => console.log("Server exited"));

使用 YouTube iframe API 提供给 Flutter 应用的 index.html 文件

<!DOCTYPE html>
<html>

<head>
    <style>
        #player 
            position: relative;
            padding-top: 56.25%;
            min-width: 240px;
            height: 0;
        

        iframe 
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
        
    </style>
    <script>
        var player;

        function onYouTubeIframeAPIReady() 
            player = new YT.Player("yt", 
                videoId: "IyFZznAk69U",
                playerVars: 
                    autoplay: 1
                
            );
        
    </script>
    <script src="https://www.youtube.com/iframe_api" async></script>
</head>

<body>
    <div id="player">
        <div id="yt"></div>
    </div>
</body>

</html>

【问题讨论】:

【参考方案1】:

您可以使用我的插件flutter_inappwebview 在 web 视图中播放 youtube 视频。

您的 youtube 视频 ID 的完整示例:

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flutter_inappwebview/flutter_inappwebview.dart';

Future main() async 
  runApp(new MyApp());


class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => new _MyAppState();


class _MyAppState extends State<MyApp> 

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

  @override
  void dispose() 
    super.dispose();
  

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
        home: InAppWebViewPage()
    );
  


class InAppWebViewPage extends StatefulWidget 
  @override
  _InAppWebViewPageState createState() => new _InAppWebViewPageState();


class _InAppWebViewPageState extends State<InAppWebViewPage> 
  InAppWebViewController webView;

  @override
  Widget build(BuildContext context) 
    return Scaffold(
        appBar: AppBar(
            title: Text("InAppWebView")
        ),
        body: Container(
            child: Column(children: <Widget>[
              Expanded(
                child: Container(
                  child: InAppWebView(
                    initialUrl: "https://www.youtube.com/embed/IyFZznAk69U",
                    initialHeaders: ,
                    initialOptions: InAppWebViewWidgetOptions(
                      inAppWebViewOptions: InAppWebViewOptions(
                        debuggingEnabled: true,
                      ),
                    ),
                    onWebViewCreated: (InAppWebViewController controller) 
                      webView = controller;
                    ,
                    onLoadStart: (InAppWebViewController controller, String url) 

                    ,
                    onLoadStop: (InAppWebViewController controller, String url) 

                    ,
                  ),
                ),
              ),
            ]))
    );
  

【讨论】:

这在 ios 上不起作用。该视频在加载 youtube 和 vimeo 时都卡住了。链接是否需要清理或像角度一样? @IanSamz 您是否将此代码添加到您的 Info.plist 文件中? &lt;key&gt;io.flutter.embedded_views_preview&lt;/key&gt; &lt;string&gt;YES&lt;/string&gt;【参考方案2】:

更新:这个插件看起来更好(在 jira 问题 url 上提到)但不是 Flutter 团队的官方插件

https://github.com/hoanglm4/flutter_youtube_view

【讨论】:

一团糟

以上是关于Flutter视频播放器,简洁!的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 视频播放器检索视频的宽度和高度

如何从在线下载视频并将其存储在本地设备上,然后使用视频播放器在 Flutter 应用程序上播放视频?

Flutter 视频播放器,如 Youtube、Amazon Prime

Flutter开发--视频播放器

Flutter 中用于 Web、移动和桌面应用程序的视频播放器?

Flutter Chewie 视频播放器 - 检查播放何时完成