MicrosoftEdge / WebView2Feedback

Feedback and discussions about Microsoft Edge WebView2
https://aka.ms/webview2
452 stars 55 forks source link

Cannot modify the currentTime of a video in HTML page displayed by SetVirtualHostNameToFolderMapping #1386

Open tro4go10 opened 3 years ago

tro4go10 commented 3 years ago

Description It is not possible to advance or rewind a video when it is displayed in a web page (in a webview2) via SetVirtualHostNameToFolderMapping

Indeed, it's possible to do "play", "pause", change volume source, but not clic on timeline. If I change currentTime with javascript the video restart in 0.

However, this same page displayed with local path, the video controler works.

I haven't error message.

Version SDK: .NEt Framework 4.7.2 VS2019 Runtime: 1.0.864.35 Framework: WinForms OS: Win10 (20H2)

Repro Steps 1/ Create a folder in your computer (by example "c:\test") 2/ In this folder, put a mp4 video named "video.mp4" and create a "index.html" file with this html code

<!DOCTYPE html>
<html>
    <body>
        <video style="width: 100%; height: 100%; " autoplay="" controls=""><source src="video.mp4" type="video/mp4"></video>
    </body>
</html>

3/ Create a new Project (Windows Forms Application in VB.NET)
4/ Install a package "Microsoft.Web.WebView2" via Nuget 5/ Add a "Windows Forms" in your Project (named Form1) 6/ Add a "Webview2" in Your forms (named WebView21), en change source for "about:blank" 7/ Modify Form1 code and add

 Public m_alreadyinit As Boolean = False
    Public Async Sub initializeAsync()
        If WebView21.CoreWebView2 IsNot Nothing Then
            If m_alreadyinit = False Then
                m_alreadyinit = True
                WebView21.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All)

                Dim opts = New CoreWebView2EnvironmentOptions With {
                .AdditionalBrowserArguments = " --disable-web-security --allow-file-access-from-files --allow-running-insecure-content"
                }
                Dim env = Await CoreWebView2Environment.CreateAsync(Nothing, "C:\test\", opts)
                Await WebView21.EnsureCoreWebView2Async(env)

                WebView21.CoreWebView2.SetVirtualHostNameToFolderMapping("myvirtualhost", "C:\test\", CoreWebView2HostResourceAccessKind.Allow)

                MyWebView2.Source = New Uri("http://myvirtualhost/test.html")
                '----> this code it's OK WebView21.Source = New Uri("file:///c:/test/test.html")
            End If
        End If
    End Sub
    Private Sub m_media_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
        initializeAsync()
    End Sub

8/ Compile, and check, It's possible to play/pause/change volume but impossible to change currenttime 9/ If I change the WebView2 source for used "New Uri("file:///c:/test/test.html")" then the change currentime works

AB#33799172

champnic commented 3 years ago

Thanks for the bug report @tro4go10 - I've added it to our backlog to take a look.

AshleyScirra commented 1 year ago

We'd like to move from using the WebResourceRequested handler to SetVirtualHostNameToFolderMapping, but this issue blocks us: it's essential that media files are seekable. As mentioned in #2679 I am pretty sure the problem is SetVirtualHostNameToFolderMapping uses 200 OK responses with the entire file data for every request. However the Chromium browser engine makes partial GET requests for media files, and expects 206 Partial Content responses with just the data ranges it requested. If it only gets 200 OK responses the media file is not seekable.

The workaround is conceptually simple but takes quite a lot of code: use WebResourceRequested, look for partial GETs, parse the byte range, and then try to figure out how to get an IStream for part of a file, which seems pretty gnarly to get done with Windows APIs. We ended up just memory mapping the entire file and using SHCreateMemStream for the appropriate range. It works, and I guess it's fine for 64-bit systems which have plenty of virtual address space.

It would be great if WebView2 could handle these details internally! It would mean we can delete a lot of custom WebResourceRequested code and just use SetVirtualHostNameToFolderMapping instead.

AshleyScirra commented 1 year ago

FWIW I also tried serving partial GETs with SHCreateStreamOnFileEx() and then calling SetSize() and Seek() on the resulting IStream to try to get it to serve the requested range, but it doesn't work - the video playback stops and fires the error event, and I can't find any more diagnostic information, so hard to know why. Perhaps WebView2 seeks the stream back to the start?

AshleyScirra commented 12 months ago

So I'm stuck again on this now working on Xbox with C++/WinRT in UWP: there doesn't seem to be the ability to memory map files. So I have to find another solution.

Does anyone know how to get a stream to just a range of a file? With StorageFile.OpenReadAsync() you can get a stream to the entire file, but as previously noted, seeking it seems to have no effect. It's a struggle to search the web for useful information. The best I can do is use DataReader to read the specified range to a buffer, and then use DataWriter to write that buffer back to a new stream. However sometimes Chromium issues very large range requests (e.g. from 1mb-200mb) when seeking a large video file, and the performance is poor as it's having to read and copy the entire chunk of data without really streaming anything. Any help appreciated.