# 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 player one provides limited features, the resolution of media playback is low, and some videos cannot be played. Through this capability, you can use a player of your own or a third party to take over web page media playback, improving 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 Use the [enableNativeMediaPlayer](../reference/apis-arkweb/arkts-basic-components-web-attributes.md#enablenativemediaplayer12) API to enable the feature 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 After this feature is enabled, the ArkWeb kernel triggers the callback registered by [onCreateNativeMediaPlayer](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#oncreatenativemediaplayer12) when a media file needs to be played on the web page. The application needs 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. * If the application takes over the web page media resource, a native media player instance is returned in the callback. The native media player needs to implement the [NativeMediaPlayerBridge](../reference/apis-arkweb/arkts-apis-webview-NativeMediaPlayerBridge.md) 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, it needs to draw the native media player component and video images on the surface provided by the ArkWeb kernel. The ArkWeb kernel combines the surface and the web page and displays them. 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, the application should save **UIContext** to use it 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. The application uses 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, the application needs to implement the [NativeMediaPlayerBridge](../reference/apis-arkweb/arkts-apis-webview-NativeMediaPlayerBridge.md) API on the native media player and operate the native media player based on the functionality of each API method. ```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