winforms 如何让YouTube原生播放器在WebView2中允许全屏?

svujldwt  于 2023-10-23  发布在  其他
关注(0)|答案(1)|浏览(88)

我正在使用WebView2浏览器允许播放一些YouTube视频,但全屏选项不可用。
我写的代码在下面。我对编码很陌生,我可能犯了很大的错误。
你需要的任何信息我都愿意提供。

public partial class HowToViewSites: CMBaseDialog
{
    private dynamic player;

    public HowToViewSites()
    {
        InitializeComponent();
        InitializeWebView2();
    }

    private async void InitializeWebView2()
    {
       
        await webView21.EnsureCoreWebView2Async(null);

        webView21.CoreWebView2.Settings.IsScriptEnabled = true;

        webView21.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted;                     
        
        string htmlContent = @"
            <html>
            <head>
            <!-- Include the YouTube iframe API script using HTTPS -->
            <script src='https://www.youtube.com/iframe_api'></script>
            </head>
            <body>
            <!-- Embed the YouTube video with enablejsapi parameter over HTTPS -->
            <iframe id='player' type='text/html' width='840' height='560'
                src='https://www.youtube.com/embed/QgMnE1No_6A?enablejsapi=1'
                frameborder='0'></iframe>

            <!-- JavaScript code to handle fullscreen changes -->
            <script>
             // Initialize the YouTube iframe API when the script is loaded
            function onYouTubeIframeAPIReady() {
            player = new YT.Player('player', {
            events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                    }
                });
            }

            function onPlayerReady(event) {
            // Player is ready
            // You can control playback and perform other actions here
            }

            function onPlayerStateChange(event) {
            // Player state has changed (e.g., video started, paused, etc.)
            // Check if the player is in fullscreen mode
                var isFullscreen = document.fullscreenElement === player.getIframe();

                if (isFullscreen) {
            // Trigger the player's native fullscreen mode
                external.RequestFullscreen();
                } else {
            // Exit fullscreen
                external.ExitFullscreen();
             }
            }

            document.addEventListener('fullscreenchange', function () {
            console.log('Fullscreen change event triggered');
            window.chrome.webview.postMessage('fullscreenchange');
            });
            </script>
            </body>
            </html>
        ";
        webView21.NavigateToString(htmlContent);

        webView21.CoreWebView2.Settings.IsWebMessageEnabled = true;
        webView21.WebMessageReceived += CoreWebView2_WebMessageReceived;            
    }

    private async void WebView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
    {
        if (e.IsSuccess)
        {
            // No need to manually call onYouTubeIframeAPIReady here
        }
        else
        {
            MessageBox.Show("WebView2 initialization failed.");
        }
    }

    private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
    {
        string message = e.TryGetWebMessageAsString();
        if (message == "enteredFullscreen")
        {
            RequestFullscreen();
        }
        else if (message == "exitedFullscreen")
        {
            ExitFullscreen();
        }
    }
            
    public void RequestFullscreen()
    {
        this.BeginInvoke(new Action(() =>
        {
            this.FormBorderStyle = FormBorderStyle.None;
            this.WindowState = FormWindowState.Maximized;
            this.TopMost = true;
            
            player.playVideo();
        }));
    }

    public void ExitFullscreen()
    {
        this.BeginInvoke(new Action(() =>
        {
            this.FormBorderStyle = FormBorderStyle.Sizable;
            this.WindowState = FormWindowState.Normal;
            this.TopMost = false;
            
            player.pauseVideo();
        }));
    }
}

非常感谢您抽出时间来帮助我。

7gcisfzg

7gcisfzg1#

几个注意事项:

  • WebView 2初始化未正确执行。你应该等待你的InitializeWebView2()方法返回Task

您可以覆盖OnLoad()方法(或订阅Load事件),使其成为“,并在此等待InitializeWebView2()

我建议不要直接使用IFrame来嵌入视频。
YouTube播放器已经具备以下功能:它可以根据传递给其构造函数的ID,用IFrame元素替换元素,IFrame元素使用创建播放器时设置的属性进行配置。
这允许例如停止/暂停/恢复回放调用JavaScript函数。你可以使用ExecuteScriptAsync()方法。
您也可以在播放器的playerVars属性中设置enablejsapi = 1
例如,这允许复制/ * 获取 * 视频的地址:

This is the one you posted:  
https://www.youtube.com/watch?v=QgMnE1No_6A

只使用它的videoId-QgMnE1No_6A-来初始化播放器
这也会启用播放器的全屏按钮。
如果你使用IFrame,你必须设置一个属性:

<iframe allowfullscreen="allowfullscreen" [...] >  </iframe>
  • 请注意,我已经将控件重命名为webView(没有原因,它就是这样:)*
public partial class HowToViewSites: CMBaseDialog
{
    public HowToViewSites() => InitializeComponent();

    protected override async void OnLoad(EventArgs e) {
        base.OnLoad(e);
        await InitializeWebView2();

        var videoSource = new Uri("https://www.youtube.com/watch?v=QgMnE1No_6A");
        var videoId = videoSource.Query.Substring(videoSource.Query.LastIndexOf("=") + 1);
        webView.NavigateToString(GetHTMLContent(videoId, new Size(840, 560)));
    }

    private async Task InitializeWebView2()
    {
       // See the docs about CoreWebView2EnvironmentOptions, you may need it
       // when your application is deployed. Now it's just set to defaults
        var options = new CoreWebView2EnvironmentOptions(null, null, "", false);
        var env = await CoreWebView2Environment.CreateAsync("", null, options);

        webView.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted;
        await webView.EnsureCoreWebView2Async(env);
    }

    private void WebView2_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e) {
        if (e.IsSuccess) {
            // These two settings are just defaults. To clarify the intention 
            webView.CoreWebView2.Settings.IsWebMessageEnabled = true;
            webView.CoreWebView2.Settings.IsScriptEnabled = true;

            webView.WebMessageReceived += async (o, a) => {
                string message = a.TryGetWebMessageAsString();
                switch (message) {
                    case "Player initialized":
                        // Starts the playback after the YT Player has been initialized
                        await Task.Delay(200);
                        await webView.ExecuteScriptAsync("ResumeVideo()");
                        break;
                    default:
                        Debug.WriteLine(message);
                        break;
                }
            };

            webView.CoreWebView2.ContainsFullScreenElementChanged += (o, a) => {
                RequestFullscreen(webView.CoreWebView2.ContainsFullScreenElement);
            };
        }
        else {
            MessageBox.Show("Core WebView component initialization failed");
            Application.ExitThread();
        }
    }

    public void RequestFullscreen(bool isFullScreen) {
        FormBorderStyle = isFullScreen ? FormBorderStyle.None : FormBorderStyle.Sizable;
        WindowState = isFullScreen ? FormWindowState.Maximized : FormWindowState.Normal;
    }
}

我已经更改了HTML和JavaScript,因此您可以使用Video ID和指定Size的页面初始化播放器:

private string GetHTMLContent(string videoId, Size videoSize) {
    var sb = new StringBuilder(@"
        <html>
        <head>
            <!-- Include the YouTube iframe API script using HTTPS -->
            <script src='https://www.youtube.com/iframe_api'></script>
            <script>
            var player;
            function onYouTubeIframeAPIReady() {
                player = new YT.Player('playerframe', {
                events: {
                    'onReady': onPlayerReady
                },
                videoId: '[VIDEO-ID]',
                height: '[VIDEO-HEIGHT]',
                width: '[VIDEO-WIDTH]',
                playerVars : {
                    'enablejsapi' : 1
                }});
            }

            function StopVideo() { player.stopVideo(); }
            function PauseVideo() { player.pauseVideo(); }
            function ResumeVideo() { player.playVideo(); }

            function onPlayerReady(event) {
                // Player is ready
                window.chrome.webview.postMessage('Player initialized');
            }
            </script>
        </head>
        <body>
            <!-- Element replaced with an IFrame when the YouType Player is initialized -->
            <div id='playerframe'></div>
        </body>
        </html>
    ");

    sb = sb.Replace("[VIDEO-ID]", videoId)
           .Replace("[VIDEO-HEIGHT]", videoSize.Height.ToString())
           .Replace("[VIDEO-WIDTH]", videoSize.Width.ToString());

    return sb.ToString();
}

现在,如果你想与播放器交互,只需调用ExecuteScriptAsync()来执行你设置的函数。现在,您可以开始/停止/恢复投资回报:

await webView.ExecuteScriptAsync("StopVideo()");
await webView.ExecuteScriptAsync("PauseVideo()");
await webView.ExecuteScriptAsync("ResumeVideo()");

相关问题