Skip to main content

A Reflex custom component wrapping react-player v3 (YouTube, Vimeo, Wistia, HLS, DASH, Mux, Spotify, Twitch, TikTok and file/audio playback).

Project description

reflex-react-player

A Reflex custom component that wraps react-player v3 — a versatile media player that plays files, audio, HLS, DASH, YouTube, Vimeo, Wistia, Mux, Spotify, Twitch and TikTok by inspecting the URL.

It gives you a Pythonic, typed API for props and events, plus imperative control (play, pause, seek, fullscreen) from your Python event handlers — and ships with a full demo app reproducing every example from the official react-player demo.

Built with Spec-Driven Design. The full specs (PRD, architecture, component contract, plan, tasks) live in docs/sdd/.

Features

  • 🎬 One component for many providers — file/audio, HLS (.m3u8), DASH (.mpd), YouTube, Vimeo, Wistia, Mux, Spotify, Twitch, TikTok.
  • 🐍 Pythonic props (snake_casecamelCase), typed with rx.Var.
  • 🔔 Events that deliver serializable media-state dicts (played, loaded, duration, ...) — not raw browser events.
  • 🎛️ Imperative control helpers: play, pause, seek_to, seek_relative, seek_fraction, set_volume, set_playback_rate, request_fullscreen, get_current_time, get_duration.
  • 🌗 Light (thumbnail-first) mode, picture-in-picture, per-player config.
  • 🧪 Smoke tests + a complete demo app.

Installation

pip install reflex-react-player

Or install from source (editable) for development:

git clone https://github.com/ecrespo/reflex-react-player.git
cd reflex-react-player
pip install -e .

Requires Reflex ≥ 0.8.0 and Python ≥ 3.10. The npm dependency (react-player@3.4.0) is added to your Reflex project automatically on build.

Quickstart

import reflex as rx
from reflex_react_player import react_player


class State(rx.State):
    playing: bool = False

    @rx.event
    def toggle(self):
        self.playing = not self.playing


def index() -> rx.Component:
    return rx.vstack(
        react_player(
            id="player",
            src="https://www.youtube.com/watch?v=oUFJJNQGwhk",
            playing=State.playing,
            controls=True,
            width="640px",
            height="360px",
            style={"aspectRatio": "16 / 9"},
        ),
        rx.button("Play / Pause", on_click=State.toggle),
    )


app = rx.App()
app.add_page(index)

Tracking progress (events)

Most events deliver a media-state dict with played (0..1), loaded (0..1), played_seconds, duration, etc.

class State(rx.State):
    played: float = 0.0
    loaded: float = 0.0
    duration: float = 0.0

    @rx.event
    def on_time_update(self, s: dict):
        self.played = s["played"]

    @rx.event
    def on_progress(self, s: dict):
        self.loaded = s["loaded"]

    @rx.event
    def on_duration(self, seconds: float):
        self.duration = seconds


react_player(
    id="player",
    src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",  # HLS
    controls=True,
    on_time_update=State.on_time_update,
    on_progress=State.on_progress,
    on_duration_change=State.on_duration,
)

Imperative control

Give the player an id, then drive it from Python:

from reflex_react_player import controls

rx.button("Play",     on_click=controls.play("player"))
rx.button("Pause",    on_click=controls.pause("player"))
rx.button("-10s",     on_click=controls.seek_relative("player", -10))
rx.button("+10s",     on_click=controls.seek_relative("player", 10))
rx.button("Fullscreen", on_click=controls.request_fullscreen("player"))

API reference

See the full contract in docs/sdd/03-component-spec.md. Summary:

Props: src, playing, loop, controls, light, volume, muted, playback_rate, pip, plays_inline, width, height, style, auto_play, preload, cross_origin, poster, disable_remote_playback, disable_picture_in_picture, preview_tab_index, preview_aria_label, o_embed_url, config.

Events: on_ready, on_start, on_play, on_pause, on_ended, on_error, on_duration_change, on_progress, on_time_update, on_seeking, on_seeked, on_waiting, on_playing, on_rate_change, on_volume_change, on_enter_picture_in_picture, on_leave_picture_in_picture, on_click_preview.

Control helpers: controls.play/pause/seek_to/seek_relative/seek_fraction/ set_volume/set_playback_rate/request_fullscreen/get_current_time/get_duration.

Per-player config

react_player(
    src="https://www.youtube.com/watch?v=oUFJJNQGwhk",
    config={"youtube": {"color": "white"}, "vimeo": {"color": "ffffff"}},
)

Keys: html, hls, dash, mux, youtube, vimeo, wistia, spotify, twitch, tiktok.

Run the demo

cd reflex_react_player_demo
pip install -e ..          # install the component
pip install -r requirements.txt
reflex init                # first time only (creates .web)
reflex run

Open http://localhost:3000 — the demo includes a provider switcher, transport controls, speed buttons, a seek slider, a volume slider, controls/muted/loop/ light toggles, the Played + Loaded progress bars, and a live time readout.

How it works

  • Client-only: react-player touches window, so the component subclasses NoSSRComponent (rendered via dynamic(import(...), {ssr:false})).
  • Default export: is_default = True (omitting it is the classic "Invalid Element Type" failure).
  • Events: native SyntheticEvents are reduced, on the client, to a small serializable dict read from the underlying HTMLMediaElement.
  • Imperative API: react-player v3 exposes its instance API through the forwarded ref (ref.currentTime, ref.play() ...); helpers drive it via rx.call_script against refs['ref_<id>'].current.

Details and decisions: docs/sdd/02-architecture.md.

Limitations

react-player v3 has not yet ported every v2 provider. DailyMotion, SoundCloud, Streamable, Facebook, Mixcloud and Kaltura are not supported here; stay on react-player v2 if you need them.

Development

pip install -e ".[dev]"
pytest -q
python -m build          # build sdist + wheel

License

Apache-2.0 © 2026 Ernesto Crespo.

react-player is a separate project by Pete Cook / Mux, under its own license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

reflex_react_player-0.1.0.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reflex_react_player-0.1.0-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file reflex_react_player-0.1.0.tar.gz.

File metadata

  • Download URL: reflex_react_player-0.1.0.tar.gz
  • Upload date:
  • Size: 17.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for reflex_react_player-0.1.0.tar.gz
Algorithm Hash digest
SHA256 840cedb0e06ac6632ed522e4c3f6f47973f9e1ea20563894484abb9aeeac999f
MD5 46b7e8faab015b7baaf10b733e5e6ae3
BLAKE2b-256 56323daddda06927713ad94dc06ae7bfaa44030b344b3679e676b47c409ff728

See more details on using hashes here.

File details

Details for the file reflex_react_player-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for reflex_react_player-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c0a5f225c06ee3c17add59881c1d9c5e40843518d40ddbb8a23f6e0a72e5368e
MD5 b99335d145f1da02a97f3c06850f7c68
BLAKE2b-256 c2888bc364911e6bef8d24e1b8770a733073e4558fa5366b1b2cf67386f5df4c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page