# VideoPlayer

## Introduction

**`VideoPlayer`** widget in Supervisely is a media player that utilizes the HTML `<video>` tag and provides additional functionalities to control it through Python code such as seeking and controlling the current playback time in seconds. It uses the built-in browser player, which is supported by most devices.

In addition, Video Player has a feature for overlaying an image on top of the video without modifying the video itself.

## Function signature

```python
VideoPlayer(url=None, mime_type="video/mp4", widget_id=None)
```

[![videoplayer-default](https://user-images.githubusercontent.com/79905215/221818450-262abd3d-a883-4f1d-bddd-d0aba35d5ff3.gif)](https://user-images.githubusercontent.com/79905215/221818450-262abd3d-a883-4f1d-bddd-d0aba35d5ff3.gif)

## Parameters

|  Parameters |  Type |                  Description                 |
| :---------: | :---: | :------------------------------------------: |
|    `url`    | `str` | Video url or local path to video on the host |
| `mime_type` | `str` |                  Video type                  |
| `widget_id` | `str` |               ID of the widget               |

### url

Video url or local path to video on the host. Determines the video to be displayed on widget.

**type:** `str`

**default value:** `None`

### mime\_type

Determines video type.

**type:** `str`

**default value:** `video/mp4`

### widget\_id

ID of the widget.

**type:** `str`

**default value:** `None`

## Methods and attributes

|                Attributes and Methods               | Description                                                   |
| :-------------------------------------------------: | ------------------------------------------------------------- |
|                        `url`                        | Get `url` property.                                           |
|                     `mime_type`                     | Get `mime_type` property.                                     |
| `set_video(url: str, mime_type: str = "video/mp4")` | Set video in `VideoPlayer` widget by url.                     |
|                       `play()`                      | Start video to play.                                          |
|                      `pause()`                      | Stop video playback.                                          |
|              `get_current_timestamp()`              | Return current video playing step.                            |
|         `set_current_timestamp(value: int)`         | Set current video playing step.                               |
|                `draw_mask(path: str)`               | Draw a mask image on top of the video without changing video. |
|                    `hide_mask()`                    | Hide the drawn mask from the video.                           |

## Mini App Example

You can find this example in our Github repository:

[ui-widgets-demos/media/005\_video\_player/src/main.py](https://github.com/supervisely-ecosystem/ui-widgets-demos/blob/master/media/005_video_player/src/main.py)

#### Import libraries

```python
import os
from pathlib import Path

import supervisely as sly
from dotenv import load_dotenv
from supervisely.app.widgets import Button, Card, Container, Checkbox
from supervisely.app.widgets import Flexbox, InputNumber, VideoPlayer
from supervisely._utils import abs_url
```

### Init API client

First, we load environment variables with credentials and init API for communicating with Supervisely Instance:

```python
load_dotenv("local.env")
load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api()
```

### Prepare videos url and type

```python
video_id = int(os.environ["modal.state.slyVideoId"])  # get video ID from environment
video_info = api.video.get_info_by_id(id=video_id)  # get VideoInfo from server
video_url = abs_url(video_info.path_original)
video_mime_type = video_info.file_meta["mime"]

local_video_url = "/static/video-cam2.mp4" # local video url
local_video_type = "video/mp4" # local video url
```

### Initialize `VideoPlayer` widgets we will use in UI

```python
video1 = VideoPlayer(url=local_video_url, mime_type=local_video_type)

video2 = VideoPlayer()
video2.set_video(url=video_url, mime_type=video_mime_type)
```

### Create a video control form

```python
play_btn = Button(text="Play", button_size="mini", icon="zmdi zmdi-play")
pause_btn = Button(text="Pause", button_size="mini", icon="zmdi zmdi-pause")

get_time_btn = Button(text="Get timestamp", button_size="mini")
input_time = InputNumber(
    value=0,
    min=0,
    max=round(video_info.file_meta["duration"], 1),
    step=0.1,
)
set_time_btn = Button(text="Set timestamp", button_size="mini")


input_sec = InputNumber(min=0.1, max=1000, step=0.1, size="small", controls=True)
forward_btn = Button(text="", button_size="mini", icon="zmdi zmdi-fast-forward", icon_gap=0)
rewind_btn = Button(text="", button_size="mini", icon="zmdi zmdi-fast-rewind", icon_gap=0)


controls_container = Flexbox(widgets=[play_btn, pause_btn])
change_timestamp_container = Flexbox(
    widgets=[rewind_btn, input_sec, forward_btn, get_time_btn, input_time, set_time_btn]
)

draw_mask_checkbox = Checkbox("draw mask on video")
mask_url = "https://user-images.githubusercontent.com/79905215/221801327-7be20a37-d4c0-4f7d-aa35-a072c4839985.png"
```

### Create app layout

Prepare a layout for app using `Card` widget with the `content` parameter and place widget that we've just created in the `Container` widget.

```python
card1 = Card(
    title="Video player",
    content=video1,
)
card2 = Card(
    title="Controls - operations from python code",
    content=Container(
        widgets=[video2, draw_mask_checkbox, controls_container, change_timestamp_container]
    ),
)

layout = Container(widgets=[card1, card2], direction="horizontal", fractions=[1, 1])
```

### Create app using layout

Define `static_dir` parameter for using files from local directory. Create an app object with `layout` parameter.

```python
static_dir = Path("media/005_video_player/videos")

app = sly.Application(layout=layout, static_dir=static_dir)
```

### Handle button clicks

Use the decorator as shown below to handle button click. We have 4 buttons: to play video, to stop video, to get timestamp, to set timestamp.

```python
@play_btn.click
def play():
    video2.play()


@pause_btn.click
def pause():
    video2.pause()


@get_time_btn.click
def get_current_timestamp():
    input_time.value = video2.get_current_timestamp()


@set_time_btn.click
def set_current_timestamp():
    time_to_set = input_time.get_value()
    video2.set_current_timestamp(time_to_set)


@draw_mask_checkbox.value_changed
def draw_mask(value):
    global g
    if value is False:
        video2.hide_mask()
        return
    video2.draw_mask(mask_url)


@forward_btn.click
def fast_forward_video():
    step = input_sec.get_value()
    if video2.url is None:
        return
    currrent_time = video2.get_current_timestamp()
    video2.set_current_timestamp(currrent_time + step)


@rewind_btn.click
def fast_rewind_video():
    step = input_sec.get_value()
    if video2.url is None:
        return
    currrent_time = video2.get_current_timestamp()
    video2.set_current_timestamp(currrent_time - step)
```

<figure><img src="https://user-images.githubusercontent.com/79905215/221830670-81099679-2627-4b6e-9a98-9b409345c7dc.gif" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.supervisely.com/app-development/widgets/media/videoplayer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
