## Message Video

The door lock's album list, alarm list, and log list have the capability to preview videos. For security reasons, the data provided by Tuya is encrypted, so the `ipc-player` component must be used to play videos normally.

### Video Cover Image

The video cover image is the corresponding image returned in the record. To display this image, please refer to [Message Image Processing Solution](/en/miniapp/solution-ai/ability/doorlock-solution/media/photo) for processing.

### Get Video Address

The video address returned in the record cannot be used directly for playback. You need to get the actual address first

```jsx
import { getMediaUrl } from '@ray-js/lock-sdk';

const mediaUrl = await getMediaUrl({
    mediaPath: data.mediaPath,
    mediaBucket: data.mediaBucket,
})
```

### Play Video

Use the `ipc-player` cross-layer component to play

```jsx
import React, { useRef } from 'react';
import { IpcPlayer } from '@ray-js/ray';
import { getMediaRotate } from '@ray-js/lock-sdk';


const { videoAngle } = getMediaRotate();
const isInit = useRef(false);
const ctx = useRef(null);

if (!ctx.current) {
    ctx.current = createIpcPlayerContext(devId);
}

// Initialize
const initPlayer = useCallback(() => {
    if (isInit.current) {
        return;
    }
    isInit.current = true;

    // Create message device instance for playback
    ctx.current?.createMessageDevice({
        devId,
        success: () => {
            // Enable sound
            if (ctx.current) {
                ctx.current.setMessageVideoMute({
                mute: 0,
                });
                ctx.current.setRotateZ(rotateInfo.videoAngle);
                // Listen after creating instance
                ipc.onPlayMessageVideoFinish(handlePlayMessageVideoFinish);
            }
        },
        fail: err => {
            ToastInstance.fail(Strings.getLang('initPlayerFailed'));
            console.warn('err createMessageDevice', err);
        },
    });

    // Create media device instance for download
    ipc.createMediaDevice({
        deviceId: devId,
    });
}, []);

// Play
const handlePlay = useCallback(async () => {
    ctx.current.startMessageVideoPlay({
        encryptKey: data.mediaKey,
        path: url,
        startTime: 0,
        success: res => {

        },
        fail: err => {
            console.warn('start fail:', err);
            ToastInstance.fail(Strings.getLang('playMediaFailed'));
        },
    });
}, [])
// Download
const handleDownload = useCallback(() => {
if (ctx.current) {
    ipc.startDownloadMessageVideo({
    deviceId: devId,
    path: mediaUrl,
    encryptKey: data.mediaKey,
    savePath: 2,
    rotateMode: rotateInfo.videoAngle || 0,
    });
}
}, [mediaUrl]);


<IpcPlayer
    type={2}
    deviceId={devId}
    autoplay={false}
    objectFit="contain"
    orientation="vertical"
    rotateZ={videoAngle}
    onCreateViewSuccess={initPlayer}
    className={styles.player}
/>
<View className={styles.tools}>
    <View className={styles.playButton} onClick={handlePlay}>
    <Icon name={Play} size="48rpx" />
    </View>
    <View className={styles.downloadButton} onClick={handleDownload}>
    <Icon name={Download} size="48rpx" />
    </View>
</View>
```

### Notes

- Since ipc-player is a cross-layer component, message videos need to be implemented on a separate page.
