video_player_control_panel 1.1.3 copy "video_player_control_panel: ^1.1.3" to clipboard
video_player_control_panel: ^1.1.3 copied to clipboard

A control panel laid on top of VideoPlayer. User can do play / pause / seekTo / set volume on it. Support closed captions / subtitle. Support fullscreen.

example/lib/main.dart

// ignore_for_file: depend_on_referenced_packages
import 'dart:developer';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player_control_panel/video_player_control_panel.dart';
import 'package:video_player/video_player.dart';
import 'package:video_player_win/video_player_win_plugin.dart';
import 'package:sprintf/sprintf.dart';

void main() {
  runApp(const MyApp());
}

String generateCaptionFileContent() {
  final sb = StringBuffer();
  for (int i = 1; i < 60 * 20; i++) {
    int minute = i ~/ 60;
    int second = i % 60;
    sb.writeln("$i");
    sb.writeln(sprintf("00:%02d:%02d,000 --> 00:%02d:%02d,900",
        [minute, second, minute, second]));
    sb.writeln("this is caption $i");
    sb.writeln("2nd line");
    sb.writeln("");
  }
  return sb.toString();
}

final g_playlist = [
  "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8",
  "https://freetestdata.com/wp-content/uploads/2022/02/Free_Test_Data_10MB_MOV.mov",
  "d:\\test\\test_youtube.mp4",
  "d:\\test\\test_4k.mp4",
  "d:\\test\\test_av1.mp4",
  "d:\\test\\test_audio.mp3",
];

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  VideoPlayerController? controller;
  PanelController panelController = PanelController();
  int nowPlayIndex = 0;

  void playPrevVideo() {
    if (nowPlayIndex <= 0) return;
    playVideo(--nowPlayIndex);
  }

  void playNextVideo() {
    if (nowPlayIndex >= g_playlist.length - 1) return;
    playVideo(++nowPlayIndex);
  }

  void playVideo(int index) {
    controller?.dispose();

    var path = g_playlist[index];
    controller = VideoPlayerController.network(path);

    var captionFile =
        Future.value(SubRipCaptionFile(generateCaptionFileContent()));
    controller!.setClosedCaptionFile(captionFile);

    setState(() {});
    controller!.initialize().then((value) {
      if (!controller!.value.isInitialized) {
        log("controller.initialize() failed");
        return;
      }

      // NOTE: web not allowed auto play without user interaction
      controller!.play();
    }).catchError((e) {
      log("controller.initialize() error occurs: $e");
    });
  }

  @override
  void initState() {
    super.initState();
    playVideo(0);
  }

  @override
  void dispose() {
    super.dispose();
    controller?.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Widget player = JkVideoControlPanel(
      controller!,
      panelController: panelController,
      showClosedCaptionButton: true,
      showFullscreenButton: true,
      showVolumeButton: true,
      //isTV: true,
      bgColor: Colors.black,
      onPrevClicked: (nowPlayIndex <= 0) ? null : playPrevVideo,
      onNextClicked:
          (nowPlayIndex >= g_playlist.length - 1) ? null : playNextVideo,
      onPlayEnded: playNextVideo,
    );

    Widget player2 = JkVideoPlaylistPlayer(
      playlist: g_playlist,
      panelController: panelController,
      showClosedCaptionButton: true,
      showFullscreenButton: true,
      isLooping: true,
      autoplay: true,
      bgColor: Colors.black,
    );

    Widget body = Row(children: [
      Expanded(child: player),
      //Expanded(child: player2), // unmark this line to show 2 videos
    ]);

    body = Focus(
      child: body,
      onKeyEvent: (node, event) {
        // test PanelController
        if (event is! KeyDownEvent) return KeyEventResult.ignored;
        if (event.logicalKey == LogicalKeyboardKey.keyP) {
          panelController.goPrev();
        } else if (event.logicalKey == LogicalKeyboardKey.keyN) {
          panelController.goNext();
        } else if (event.logicalKey == LogicalKeyboardKey.keyT) {
          if (!panelController.isFullscreen()) {
            panelController.enterFullscreen();
            Future.delayed(const Duration(seconds: 3)).then((_) {
              if (panelController.isFullscreen()) {
                panelController.exitFullscreen();
              }
            });
          }
          return KeyEventResult.handled;
        }
        return KeyEventResult.ignored;
      },
    );

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Example app'),
        ),
        body: body,
      ),
    );
  }
}
16
likes
150
points
674
downloads

Publisher

unverified uploader

Weekly Downloads

A control panel laid on top of VideoPlayer. User can do play / pause / seekTo / set volume on it. Support closed captions / subtitle. Support fullscreen.

Repository (GitHub)
View/report issues

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter, flutter_web_plugins, fullscreen_window, plugin_platform_interface, sprintf, video_player, video_player_win

More

Packages that depend on video_player_control_panel