# Taking Over the Media Playback on Web Pages The **Web** component provides the capability for applications to take over media playback on web pages, which improves media playback qualities on the web page. ## When to Use On web pages, media players are simple and provide few functions, with lower video quality and some videos cannot be played. In this case, you can use your own or a third-party player to take over web page media playback to improve media playback experience. ## Implementation Principle ### Framework of Using the ArkWeb Kernel to Play Media When web media playback takeover is disabled, the playback architecture of the ArkWeb kernel is as follows: ![arkweb media pipeline](figures/arkweb_media_pipeline.png) > **NOTE** > > - In the preceding figure, step 1 indicates that the ArkWeb kernel creates a **WebMediaPlayer** to play media resources on web pages. > - Step 2 indicates that the **WebMediaPlayer** uses the system decoder to render media data. When web media playback takeover is enabled, the playback architecture of the ArkWeb kernel is as follows: ![arkweb native media player](figures/arkweb_native_media_player.png) > **NOTE** > > - In the preceding figure, step 1 indicates that the ArkWeb kernel creates a **WebMediaPlayer** to play media resources on web pages. > - Step 2 indicates that **WebMediaPlayer** uses **NativeMediaPlayer** provided by the application to render media data. ### Interactions Between the ArkWeb Kernel and Application ![interactions between arkweb and native media player](figures/interactions_between_arkweb_and_native_media_player.png) > **NOTE** > > - For details about step 1 in the preceding figure, see [Enabling Web Media Playback Takeover](#enabling-web-media-playback-takeover). > - For details about step 2, see [Creating a Native Media Player](#creating-a-native-media-player). > - For details about step 3, see [Drawing Native Media Player Components](#drawing-native-media-player-components). > - For details about step 4, see [Executing Playback Control Commands Sent by ArkWeb Kernel to the Native Media Player](#executing-playback-control-commands-sent-by-arkweb-kernel-to-the-native-media-player). > - For details about step 5, see [Notifying the Status Information of Native Media Player to the ArkWeb Kernel](#notifying-the-status-information-of-native-media-player-to-the-arkweb-kernel). ## How to Develop ### Enabling Web Media Playback Takeover You need to use the [enableNativeMediaPlayer](../reference/apis-arkweb/ts-basic-components-web.md#enablenativemediaplayer12) API to enable the function of taking over web page media playback. ```ts // xxx.ets import { webview } from '@kit.ArkWeb'; @Entry @Component struct WebComponent { controller: webview.WebviewController = new webview.WebviewController(); build() { Column() { Web({ src: 'www.example.com', controller: this.controller }) .enableNativeMediaPlayer({ enable: true, shouldOverlay: false }) } } } ``` ### Creating a Native Media Player Once web media playback takeover is enabled, the ArkWeb kernel triggers the callback registered by [onCreateNativeMediaPlayer](../reference/apis-arkweb/js-apis-webview.md#oncreatenativemediaplayer12) each time a media file needs to be played on the web page. You need to register a callback for creating a native media player by invoking **onCreateNativeMediaPlayer**. The callback function determines whether to create a native media player to take over the web page media resources based on the media information. * If the application does not take over the web page media resource, **null** is returned in the callback function. * If the application takes over the web page media resource, a native media player instance is returned in the callback function. The native media player needs to implement the [NativeMediaPlayerBridge](../reference/apis-arkweb/js-apis-webview.md#nativemediaplayerbridge12) API so that the ArkWeb kernel can control the playback on the native media player. ```ts // xxx.ets import { webview } from '@kit.ArkWeb'; // Implement the webview.NativeMediaPlayerBridge API. // The ArkWeb kernel calls the webview.NativeMediaPlayerBridge methods to control playback on NativeMediaPlayer. class NativeMediaPlayerImpl implements webview.NativeMediaPlayerBridge { // ...Implement the APIs in NativeMediaPlayerBridge... constructor(handler: webview.NativeMediaPlayerHandler, mediaInfo: webview.MediaInfo) {} updateRect(x: number, y: number, width: number, height: number) {} play() {} pause() {} seek(targetTime: number) {} release() {} setVolume(volume: number) {} setMuted(muted: boolean) {} setPlaybackRate(playbackRate: number) {} enterFullscreen() {} exitFullscreen() {} } @Entry @Component struct WebComponent { controller: webview.WebviewController = new webview.WebviewController(); build() { Column() { Web({ src: 'www.example.com', controller: this.controller }) .enableNativeMediaPlayer({ enable: true, shouldOverlay: false }) .onPageBegin((event) => { this.controller.onCreateNativeMediaPlayer((handler: webview.NativeMediaPlayerHandler, mediaInfo: webview.MediaInfo) => { // Determine whether to take over the media. if (!shouldHandle(mediaInfo)) { // The native media player does not take over the media. // Return null. The ArkWeb kernel will play the media with the web media player. return null; } // Take over the web media. // Return a native media player instance to the ArkWeb kernel. let nativePlayer: webview.NativeMediaPlayerBridge = new NativeMediaPlayerImpl(handler, mediaInfo); return nativePlayer; }); }) } } } // stub function shouldHandle(mediaInfo: webview.MediaInfo) { return true; } ``` ### Drawing Native Media Player Components When an application takes over the media playback on web pages, you need to draw the native media player component and video images on the surface provided by the ArkWeb kernel. Then the ArkWeb kernel combines the surface with the web page and displays it on the screen. This process is the same as that of [Rendering and Drawing XComponent+AVPlayer and Button Components at the Same Layer](web-same-layer.md#) 1. In the application startup phase, **UIContext** must be saved so that it can be used in subsequent rendering and drawing processes at the same layer. ```ts // xxxAbility.ets import { UIAbility } from '@kit.AbilityKit'; import { window } from '@kit.ArkUI'; export default class EntryAbility extends UIAbility { onWindowStageCreate(windowStage: window.WindowStage): void { windowStage.loadContent('pages/Index', (err, data) => { if (err.code) { return; } // Save UIContext, which will be used in subsequent rendering and drawing at the same layer. AppStorage.setOrCreate("UIContext", windowStage.getMainWindowSync().getUIContext()); }); } // ...Other APIs that need to be overridden... } ``` 2. Use the surface created by the ArkWeb kernel for rendering and drawing at the same layer. ```ts // xxx.ets import { webview } from '@kit.ArkWeb'; import { BuilderNode, FrameNode, NodeController, NodeRenderType } from '@kit.ArkUI'; interface ComponentParams {} class MyNodeController extends NodeController { private rootNode: BuilderNode<[ComponentParams]> | undefined; constructor(surfaceId: string, renderType: NodeRenderType) { super(); // Obtain the saved UIContext. let uiContext = AppStorage.get("UIContext"); this.rootNode = new BuilderNode(uiContext as UIContext, { surfaceId: surfaceId, type: renderType }); } makeNode(uiContext: UIContext): FrameNode | null { if (this.rootNode) { return this.rootNode.getFrameNode() as FrameNode; } return null; } build() { // Construct the native media player component. } } @Entry @Component struct WebComponent { node_controller?: MyNodeController; controller: webview.WebviewController = new webview.WebviewController(); @State show_native_media_player: boolean = false; build() { Column() { Stack({ alignContent: Alignment.TopStart }) { if (this.show_native_media_player) { NodeContainer(this.node_controller) .width(300) .height(150) .backgroundColor(Color.Transparent) .border({ width: 2, color: Color.Orange }) } Web({ src: 'www.example.com', controller: this.controller }) .enableNativeMediaPlayer({ enable: true, shouldOverlay: false }) .onPageBegin((event) => { this.controller.onCreateNativeMediaPlayer((handler: webview.NativeMediaPlayerHandler, mediaInfo: webview.MediaInfo) => { // Take over the web media. // Use the surface provided by the rendering at the same layer to construct a native media player component. this.node_controller = new MyNodeController(mediaInfo.surfaceInfo.id, NodeRenderType.RENDER_TYPE_TEXTURE); this.node_controller.build(); // Show the native media player component. this.show_native_media_player = true; // Return a native media player instance to the ArkWeb kernel. return null; }); }) } } } } ``` For details about how to dynamically create components and draw them on the surface, see [Rendering and Drawing XComponent+AVPlayer and Button Components at the Same Layer](web-same-layer.md#). ### Executing Playback Control Commands Sent by ArkWeb Kernel to the Native Media Player To facilitate the control over native media player by the ArkWeb kernel, you need to implement the [NativeMediaPlayerBridge](../reference/apis-arkweb/js-apis-webview.md#nativemediaplayerbridge12) API on the native media player and operate the native media player based on the function of each API. ```ts // xxx.ets import { webview } from '@kit.ArkWeb'; class ActualNativeMediaPlayerListener { constructor(handler: webview.NativeMediaPlayerHandler) {} } class NativeMediaPlayerImpl implements webview.NativeMediaPlayerBridge { constructor(handler: webview.NativeMediaPlayerHandler, mediaInfo: webview.MediaInfo) { // 1. Create a listener for the native media player. let listener: ActualNativeMediaPlayerListener = new ActualNativeMediaPlayerListener(handler); // 2. Create a native media player. // 3. Listen for the native media player. // ... } updateRect(x: number, y: number, width: number, height: number) { // The position and size of the