Nova Player

pub package license

Nova Player is a Flutter video player with built-in analytics and a clean custom-controls API. It’s backed by xstream_player and uses a BLoC/repository architecture internally, but exposes a simple public surface so you don’t have to depend on the internals.

What is visible to you (public API)

  • VideoPlayer widget for playback
  • NovaPlayerController for custom controls (streams + commands)
  • Streams: player state, media progress, interactions, and convenience helpers

What’s implemented internally (not public)

  • BLoCs, repositories, data sources
  • Analytics wiring and collectors
  • BetterPlayer internals (a read-only controller is available via rawController for advanced use)

Installation

Add to your pubspec.yaml:

dependencies:
  nova_player: ^0.1.0

Import:

import 'package:nova_player/nova_player.dart';

Quick start

Default controls

VideoPlayer(
  appId: 'YOUR_APP_ID',
  streamCode: 'YOUR_STREAM_CODE',
  userContext: {'user_id': '123'}, // optional
)

Use NovaPlayerController as your single source of truth for streams and commands. Pass the same controller to the VideoPlayer and to your custom overlay.

final controller = NovaPlayerController();

VideoPlayer(
  appId: 'YOUR_APP_ID',
  streamCode: 'YOUR_STREAM_CODE',
  controller: controller,
  controls: MyControls(controller: controller),
)

Minimal custom controls example:

class MyControls extends StatelessWidget {
  final NovaPlayerController controller;
  const MyControls({super.key, required this.controller});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(12),
      alignment: Alignment.bottomCenter,
      child: Row(
        children: [
          StreamBuilder<bool>(
            stream: controller.isPlayingStream,
            builder: (_, s) => IconButton(
              icon: Icon((s.data ?? false) ? Icons.pause : Icons.play_arrow),
              onPressed: controller.togglePlay,
            ),
          ),
          const SizedBox(width: 8),
          Expanded(
            child: StreamBuilder<MediaProgress>(
              stream: controller.mediaProgressStream,
              builder: (_, snap) {
                final p = snap.data?.progress ?? Duration.zero;
                final d = snap.data?.totalDuration ?? Duration.zero;
                final max = d.inSeconds == 0 ? 1.0 : d.inSeconds.toDouble();
                return Slider(
                  value: p.inSeconds.clamp(0, max.toInt()).toDouble(),
                  max: max,
                  onChanged: (v) => controller.seekTo(Duration(seconds: v.toInt())),
                );
              },
            ),
          ),
          IconButton(
            onPressed: controller.enterFullscreen,
            icon: const Icon(Icons.fullscreen),
          ),
        ],
      ),
    );
  }
}

See a full example in example/lib/main.dart.


Public API

Widgets

  • VideoPlayer({required String appId, required String streamCode, Map<String, dynamic>? userContext, Widget? controls, NovaPlayerController? controller})
    • Default controls are shown if controls is not provided.
    • To build custom controls, pass a NovaPlayerController and your custom controls widget.

Controller: NovaPlayerController

Streams (broadcast):

  • playerStateStream: Stream<VideoPlayerState>
  • mediaProgressStream: Stream<MediaProgress>
  • interactionStream: Stream<PlayerInteraction>
  • videoValueStream: Stream<VideoPlayerValue>
  • Convenience: isPlayingStream, positionStream, durationStream

Commands:

  • play(), pause(), togglePlay()
  • seekTo(Duration), seekRelative(Duration)
  • setVolume(double), mute(), unmute()
  • toggleLooping()
  • setPlaybackSpeed(double)
  • selectTrack(BetterPlayerAsmsTrack)
  • enterFullscreen(), exitFullscreen()
  • reset()
  • postInteraction(PlayerInteraction)

Advanced:

  • rawController: BetterPlayerController (use sparingly; API may change)

Notes:

  • The controller is attached automatically by the player when provided.
  • Internal BLoCs are not part of the public API.

Analytics

Analytics and interaction tracking are built in. You can observe interactions via interactionStream or emit your own via postInteraction from custom controls.


Platform support

  • Android, iOS (uses xstream_player under the hood)

Contributing

Issues and PRs are welcome.


License

MIT © Nova Player Contributors

Libraries

nova_player