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

Posted

技术标签:

【中文标题】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 WebView 插件无法播放某些 YouTube 视频的主要内容,如果未能解决你的问题,请参考以下文章

webview_flutter 无法隐藏/更改某些元素

Flutter - 如何使用 webview_flutter 包播放 Google Drive 视频预览

Flutter - 无法从 Webview 下载文件

Flutter:如何在 webview 中阻止全屏视频?

如何使用 flutter_webview 插件在 Flutter 中启用位置?

在flutter webview中播放视频时,有没有办法打开像MX播放器这样的外部视频播放器? [关闭]