目录

如何解决ArkWeb视频播放异常问题

问题现象

Web组件播放视频异常,这类问题要如何定位解决?

背景知识

解决方案

Web加载视频播放出现异常问题时,可按如下步骤进行定位排查:

  1. 确保真机正常联网,并在工程中的module.json5配置文件中添加网络权限:ohos.permission.INTERNET,具体申请方式请参考声明权限。如果使用的是模拟器,需要检查模拟器是否无法连接网络,通常是由于网络代理的原因,按照指引配置即可。
  2. 对于通过src直接加载在线视频地址链接的场景:
    • 首先尝试在浏览器中打开该网址,若该网址可以正常打开,则检查是否是因为domStorageAccess和mixedMode属性配置错误的原因。
    • 对于浏览器打开后直接下载的视频链接,需要将文件先下载后再进行加载:
    import { webview } from '@kit.ArkWeb';
    
    @Entry
    @Component
    struct DownloadVideoDemo {
      controller: webview.WebviewController = new webview.WebviewController();
      delegate: webview.WebDownloadDelegate = new webview.WebDownloadDelegate();
      cacheDir: string = this.getUIContext().getHostContext()!.cacheDir;
    
      build() {
        Column() {
          Web({
            src: 'xxx.com/xxx.mp4', // 需要替换为那种打开后自动下载的链接
            controller: this.controller
          })
            .fileAccess(true)
            .domStorageAccess(true)
            .geolocationAccess(false)
            .onControllerAttached(() => {
              try {
                this.delegate.onBeforeDownload((webDownloadItem: webview.WebDownloadItem) => {
                  // 传入本地沙箱路径并开始下载
                  webDownloadItem.start(this.cacheDir + '/' + webDownloadItem.getSuggestedFileName());
                });
                this.delegate.onDownloadUpdated((webDownloadItem: webview.WebDownloadItem) => {
                  // 下载任务进度和速度监测处理
                  console.info(`download update guid: ${webDownloadItem.getGuid()}`);
                });
                this.delegate.onDownloadFailed((webDownloadItem: webview.WebDownloadItem) => {
                  // 下载任务失败处理
                  console.error(`download failed guid: ${webDownloadItem.getGuid()}`);
                });
                this.delegate.onDownloadFinish((webDownloadItem: webview.WebDownloadItem) => {
                  // 下载成功通过Web重新加载本地文件打开预览
                  this.controller.loadUrl(`file://${this.cacheDir}/` + webDownloadItem.getSuggestedFileName());
                });
                this.controller.setDownloadDelegate(this.delegate);
              } catch (error) {
                // 异常处理
                console.error(
                  `ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
              }
            });
        };
      }
    }
  3. 对于通过src加载本地视频文件的场景,需要检查是否开启fileAccess权限:
    import { webview } from '@kit.ArkWeb';
    
    @Entry
    @Component
    struct SandboxVideoDemo {
      controller: webview.WebviewController = new webview.WebviewController();
      url: string | Resource = this.getUIContext().getHostContext()!.filesDir + '/test.mp4';
    
      build() {
        Column() {
          Web({
            src: this.url,
            controller: this.controller
          })
            .domStorageAccess(true)
            .fileAccess(true)
            .geolocationAccess(false);
        };
      }
    }
  4. 对于通过src加载本地H5页面,H5页面中通过video标签加载一个视频的场景:
    import { webview } from '@kit.ArkWeb';
    
    @Entry
    @Component
    struct LocalH5Demo {
      controller: webview.WebviewController = new webview.WebviewController();
    
      build() {
        Column() {
          Web({
            src: $rawfile('video.html'),
            controller: this.controller
          })
            .geolocationAccess(false)
            .fileAccess(true);
        };
      }
    }
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width">
    </head>
    <body>
    <video id="myVideo" src="resource://rawfile/file/video.mp4" autoplay controls muted >
    </video>
    <script>
    </script>
    </body>
    </html>
  5. 涉及到跨域的话,请参考Web页面跨域解决方案。

常见FAQ

Q:H5中video组件如果没有设置poster兜底图时,低版本WebView内核是否会崩溃?

A:HarmonyOS上的poster逻辑对失败的情况做了处理,因而不会崩溃。