brighton_video_player
A Flutter video player package with built-in caching support.
中文说明请见 README.zh-CN.md。
Features
- Unified controller API for play/pause/seek/fullscreen
- Caching helpers (
preCache, background download, cache check, cache removal) - Proxy-to-origin fallback for safer playback startup
BoxFitsupport for both poster and video rendering- A ready-to-use player widget:
BrightonVideoPlayer - UI delegate extension point for custom skins
Install
Add to your app pubspec.yaml:
dependencies:
brighton_video_player: ^1.0.2
Then run:
flutter pub get
Bootstrap
If you want caching support, initialize the package once before runApp:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await BrightonVideoBootstrap.ensureInitialized();
runApp(const MyApp());
}
If you skip this step, direct playback can still work, but local proxy caching features may not be ready when playback starts.
Quick Start
import 'package:flutter/material.dart';
import 'package:brighton_video_player/brighton_video_player.dart';
class VideoDemoPage extends StatefulWidget {
const VideoDemoPage({super.key});
@override
State<VideoDemoPage> createState() => _VideoDemoPageState();
}
class _VideoDemoPageState extends State<VideoDemoPage> {
late final BrightonVideoController _controller;
@override
void initState() {
super.initState();
_controller = BrightonVideoController(
sourceUrl: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
autoPlay: true,
loop: true,
httpHeaders: const {
// 'Authorization': 'Bearer <token>',
},
// customCacheId: 'user-123-video-A',
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: BrightonVideoPlayer(
controller: _controller,
fit: BoxFit.cover,
posterUrl: 'https://example.com/poster.jpg',
autoRotate: true,
),
),
);
}
}
Playback Strategy
BrightonVideoController supports three playback routing modes:
BrightonPlaybackStrategy.auto: prefer direct playback, but use proxy when the file is already fully cachedBrightonPlaybackStrategy.directOnly: always play the original URLBrightonPlaybackStrategy.proxyPreferred: prefer local proxy first and fall back to origin if proxy startup fails
For most apps, auto is the safest default.
Cache API
BrightonVideoController exposes:
Future<void> preCache({bool downloadNow = true})Future<void> downloadInBackground()Future<bool> isCached({bool checkFull = false})Future<void> removeCache({bool singleFile = false})
Example:
final cached = await _controller.isCached(checkFull: true);
if (!cached) {
await _controller.preCache(downloadNow: true);
}
For authenticated media, pass the same httpHeaders to the controller so playback and cache lookup stay aligned.
Example
The included example app demonstrates:
- standard playback with poster support
- fullscreen toggle
- cache status inspection
- pre-cache, full download, and remove-cache actions
- debug route overlay for proxy/direct playback
Run it with:
cd example
flutter pub get
flutter run
Custom UI Delegate
Pass your own delegate to BrightonVideoPlayer(uiDelegate: ...):
import 'package:flutter/material.dart';
import 'package:brighton_video_player/brighton_video_player.dart';
class SimpleUiDelegate extends BrightonVideoUiDelegate {
@override
Widget buildBackground(BuildContext context, bool showControls) {
return Container(color: showControls ? Colors.black38 : Colors.transparent);
}
@override
Widget buildTopBar(
BuildContext context,
BrightonVideoController controller,
bool showControls,
) {
return const SizedBox.shrink();
}
@override
Widget buildCenterControl(
BuildContext context,
BrightonVideoController controller,
bool showControls,
bool isScrubbing,
VoidCallback restartControls,
) {
return const SizedBox.shrink();
}
@override
Widget buildBottomBar(
BuildContext context,
BrightonVideoController controller,
bool showControls,
bool isScrubbing,
Duration displayPosition,
ValueChanged<Duration> onSeek,
) {
return const SizedBox.shrink();
}
@override
Widget buildLoading(BuildContext context) =>
const Center(child: CircularProgressIndicator());
@override
Widget buildError(
BuildContext context,
String errorMsg,
VoidCallback onRetry,
) {
return Center(child: Text(errorMsg));
}
@override
Widget buildPoster(BuildContext context, String? posterUrl, BoxFit fit) {
return Container(color: Colors.black);
}
}
Notes
BrightonVideoPlayerowns presentation only. Playback state and cache actions live onBrightonVideoController.fitapplies to the video surface as well as the poster.- The default UI is intentionally minimal. Use a custom delegate if you need branding, extra buttons, or different gestures.
Migration Notes
Old names are still available as compatibility aliases:
CachedVideoPlayer->BrightonVideoPlayerJVideoController->BrightonVideoControllerBrightonVideoUiDelegate->JVideoUIDelegate
For new code, use the Brighton* names.