Git Product home page Git Product logo

Comments (6)

brianegan avatar brianegan commented on June 6, 2024 1

Hey hey :) I'm not quite sure Chewie is the right tool for audio playback. It relies on the video_player plugin, which is tailor-made for delivering video content to a Flutter app by forwarding texture information from ExoPlayer or AVPlayer, and doesn't officially support audio playback and all of the intricacies involved with that (and there are a lot). Since these two tools support audio, it works, but I really feel it's using the wrong tool for the job.

In addition, I don't know if it's a great idea to support both audio and video from this one package. I could see many use-cases making sense for audio but not video and vice-versa, and supporting all of those throughout the code with if statements is going to be a maintenance headache going forward.

I think it would make more sense to fork Chewie and use a proper audio-player plugin that doesn't incur the overhead of trying to deliver video content to Flutter, and gives the flexibility of delivering an experience that can really focus on audio (sleep timers, 2x playback, background playing, not going into full screen mode when the device is rotated, etc).

from chewie.

Sub6Resources avatar Sub6Resources commented on June 6, 2024 1

Hey @brianegan and @cbenhagen, just wanted to let you know I've created a fork of Chewie for audio only playback that hides the video box. It's published at https://pub.dev/packages/chewie_audio.

I've tentatively kept both of you as authors of the package on Pub, since most of the codebase comes from your contributions. I'm not sure if Pub notifies all authors or just uploaders when a new version is pushed, so let me know if you would like to be removed as an author for the package.

from chewie.

jeffmikels avatar jeffmikels commented on June 6, 2024

I have finished the implementation. How should I submit the pull request?

Here is the diff from v0.5.0.

diff --git a/lib/src/chewie_player.dart b/lib/src/chewie_player.dart
index b249a82..1a04e45 100644
--- a/lib/src/chewie_player.dart
+++ b/lib/src/chewie_player.dart
@@ -27,6 +27,9 @@ class Chewie extends StatefulWidget {
   /// Whether or not to show the controls
   final bool showControls;
 
+  /// Whether or not to display a video box
+  final bool showVideoBox;
+
   /// The Aspect Ratio of the Video. Important to get the correct size of the
   /// video!
   ///
@@ -56,6 +59,7 @@ class Chewie extends StatefulWidget {
     this.materialProgressColors,
     this.placeholder,
     this.showControls = true,
+    this.showVideoBox = true,
   })  : assert(controller != null,
             'You must provide a controller to play a video'),
         super(key: key);
@@ -80,6 +84,7 @@ class _ChewiePlayerState extends State<Chewie> {
       placeholder: widget.placeholder,
       autoPlay: widget.autoPlay,
       showControls: widget.showControls,
+      showVideoBox: widget.showVideoBox,
     );
   }
 
diff --git a/lib/src/cupertino_controls.dart b/lib/src/cupertino_controls.dart
index 2a08c2f..112b98f 100644
--- a/lib/src/cupertino_controls.dart
+++ b/lib/src/cupertino_controls.dart
@@ -18,6 +18,7 @@ class CupertinoControls extends StatefulWidget {
   final bool fullScreen;
   final ChewieProgressColors progressColors;
   final bool autoPlay;
+  final bool hasVideo;
 
   CupertinoControls({
     @required this.backgroundColor,
@@ -27,6 +28,7 @@ class CupertinoControls extends StatefulWidget {
     @required this.fullScreen,
     @required this.progressColors,
     @required this.autoPlay,
+    this.hasVideo = true,
   });
 
   @override
@@ -53,13 +55,15 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     final barHeight = orientation == Orientation.portrait ? 30.0 : 47.0;
     final buttonPadding = orientation == Orientation.portrait ? 16.0 : 24.0;
 
+    List<Widget> widgets = [];
+    if (widget.hasVideo) {
+      widgets.add(_buildTopBar(backgroundColor, iconColor, controller, barHeight, buttonPadding));
+      widgets.add(_buildHitArea());
+    }
+    widgets.add(_buildBottomBar(backgroundColor, iconColor, controller, barHeight));
+
     return new Column(
-      children: <Widget>[
-        _buildTopBar(
-            backgroundColor, iconColor, controller, barHeight, buttonPadding),
-        _buildHitArea(),
-        _buildBottomBar(backgroundColor, iconColor, controller, barHeight),
-      ],
+      children: widgets,
     );
   }
 
@@ -80,6 +84,7 @@ class _CupertinoControlsState extends State<CupertinoControls> {
   void initState() {
     _initialize();
 
+    if (! widget.hasVideo) _hideStuff = false;
     super.initState();
   }
 
@@ -385,7 +390,7 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     setState(() {
       _hideStuff = false;
 
-      _startHideTimer();
+      if (widget.hasVideo) _startHideTimer();
     });
   }
 
@@ -397,7 +402,7 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     if ((widget.controller.value != null &&
             widget.controller.value.isPlaying) ||
         widget.autoPlay) {
-      _startHideTimer();
+      if (widget.hasVideo) _startHideTimer();
     }
 
     _initTimer = new Timer(new Duration(milliseconds: 200), () {
@@ -409,7 +414,7 @@ class _CupertinoControlsState extends State<CupertinoControls> {
 
   void _onExpandCollapse() {
     setState(() {
-      _hideStuff = true;
+      if (widget.hasVideo) _hideStuff = true;
 
       widget.onExpandCollapse().then((dynamic _) {
         _expandCollapseTimer = new Timer(new Duration(milliseconds: 300), () {
@@ -431,7 +436,7 @@ class _CupertinoControlsState extends State<CupertinoControls> {
             _hideTimer?.cancel();
           },
           onDragEnd: () {
-            _startHideTimer();
+            if (widget.hasVideo) _startHideTimer();
           },
           colors: widget.progressColors ??
               new ChewieProgressColors(
@@ -505,7 +510,7 @@ class _CupertinoControlsState extends State<CupertinoControls> {
   void _startHideTimer() {
     _hideTimer = new Timer(const Duration(seconds: 3), () {
       setState(() {
-        _hideStuff = true;
+        if (widget.hasVideo) _hideStuff = true;
       });
     });
   }
diff --git a/lib/src/material_controls.dart b/lib/src/material_controls.dart
index 5c01696..cb68ae7 100644
--- a/lib/src/material_controls.dart
+++ b/lib/src/material_controls.dart
@@ -13,6 +13,7 @@ class MaterialControls extends StatefulWidget {
   final Future<dynamic> Function() onExpandCollapse;
   final ChewieProgressColors progressColors;
   final bool autoPlay;
+  final bool hasVideo;
 
   MaterialControls({
     @required this.controller,
@@ -20,6 +21,7 @@ class MaterialControls extends StatefulWidget {
     @required this.onExpandCollapse,
     @required this.progressColors,
     @required this.autoPlay,
+    this.hasVideo = true,
   });
 
   @override
@@ -44,7 +46,7 @@ class _MaterialControlsState extends State<MaterialControls> {
   Widget build(BuildContext context) {
     return new Column(
       children: <Widget>[
-        _buildHitArea(),
+        widget.hasVideo ? _buildHitArea() : Container(),
         _buildBottomBar(context, widget.controller),
       ],
     );
@@ -65,6 +67,7 @@ class _MaterialControlsState extends State<MaterialControls> {
 
   @override
   void initState() {
+    if (!widget.hasVideo) _hideStuff = false;
     _initialize();
 
     super.initState();
@@ -243,7 +246,7 @@ class _MaterialControlsState extends State<MaterialControls> {
 
   void _cancelAndRestartTimer() {
     _hideTimer?.cancel();
-    _startHideTimer();
+    if (widget.hasVideo) _startHideTimer();
 
     setState(() {
       _hideStuff = false;
@@ -258,7 +261,7 @@ class _MaterialControlsState extends State<MaterialControls> {
     if ((widget.controller.value != null &&
             widget.controller.value.isPlaying) ||
         widget.autoPlay) {
-      _startHideTimer();
+      if (widget.hasVideo) _startHideTimer();
     }
 
     _showTimer = new Timer(new Duration(milliseconds: 200), () {
@@ -270,7 +273,7 @@ class _MaterialControlsState extends State<MaterialControls> {
 
   void _onExpandCollapse() {
     setState(() {
-      _hideStuff = true;
+      if (widget.hasVideo) _hideStuff = true;
 
       widget.onExpandCollapse().then((dynamic _) {
         _showAfterExpandCollapseTimer =
@@ -306,7 +309,7 @@ class _MaterialControlsState extends State<MaterialControls> {
   void _startHideTimer() {
     _hideTimer = new Timer(const Duration(seconds: 3), () {
       setState(() {
-        _hideStuff = true;
+        if (widget.hasVideo) _hideStuff = true;
       });
     });
   }
@@ -335,7 +338,7 @@ class _MaterialControlsState extends State<MaterialControls> {
               _dragging = false;
             });
 
-            _startHideTimer();
+            if (widget.hasVideo) _startHideTimer();
           },
           colors: widget.progressColors ??
               new ChewieProgressColors(
diff --git a/lib/src/player_with_controls.dart b/lib/src/player_with_controls.dart
index 34e2a8d..dbd3977 100644
--- a/lib/src/player_with_controls.dart
+++ b/lib/src/player_with_controls.dart
@@ -18,6 +18,7 @@ class PlayerWithControls extends StatefulWidget {
   final double aspectRatio;
   final bool autoPlay;
   final bool showControls;
+  final bool showVideoBox;
 
   PlayerWithControls({
     Key key,
@@ -26,6 +27,7 @@ class PlayerWithControls extends StatefulWidget {
     @required this.aspectRatio,
     this.fullScreen = false,
     this.showControls = true,
+    this.showVideoBox = true,
     this.cupertinoProgressColors,
     this.materialProgressColors,
     this.placeholder,
@@ -43,43 +45,67 @@ class _VideoPlayerWithControlsState extends State<PlayerWithControls> {
   Widget build(BuildContext context) {
     final controller = widget.controller;
 
-    return new Center(
-      child: new Container(
-        width: MediaQuery.of(context).size.width,
-        child: widget.fullScreen &&
-                MediaQuery.of(context).orientation == Orientation.landscape
-            ? _buildPlayerWithControls(controller, context)
-            : new AspectRatio(
-                aspectRatio: widget.aspectRatio,
-                child: _buildPlayerWithControls(controller, context),
-              ),
-      ),
-    );
+    if (widget.showVideoBox) {
+      return new Center(
+        child: new Container(
+          width: MediaQuery.of(context).size.width,
+          child: widget.fullScreen &&
+                  MediaQuery.of(context).orientation == Orientation.landscape
+              ? _buildPlayerWithControls(controller, context)
+              : new AspectRatio(
+                  aspectRatio: widget.aspectRatio,
+                  child: _buildPlayerWithControls(controller, context),
+                ),
+        ),
+      );
+    }
+    else {
+      return new Center(
+        child: _buildPlayerWithControls(controller, context),
+      );
+    }
   }
 
   Container _buildPlayerWithControls(
       VideoPlayerController controller, BuildContext context) {
-    return new Container(
-      child: new Stack(
-        children: <Widget>[
-          widget.placeholder ?? new Container(),
-          new Center(
-            child: new Hero(
-              tag: controller,
-              child: widget.fullScreen &&
-                      MediaQuery.of(context).orientation ==
-                          Orientation.landscape
-                  ? new VideoPlayer(controller)
-                  : new AspectRatio(
-                      aspectRatio: widget.aspectRatio,
-                      child: new VideoPlayer(controller),
-                    ),
+    if (widget.showVideoBox) {
+      return new Container(
+        color:Colors.black,
+        child: new Stack(
+          children: <Widget>[
+            widget.placeholder ?? new Container(),
+            new Center(
+              child: new Hero(
+                tag: controller,
+                child: widget.fullScreen &&
+                        MediaQuery.of(context).orientation ==
+                            Orientation.landscape
+                    ? new VideoPlayer(controller)
+                    : new AspectRatio(
+                        aspectRatio: widget.aspectRatio,
+                        child: new VideoPlayer(controller),
+                      ),
+              ),
             ),
-          ),
-          _buildControls(context, controller),
-        ],
-      ),
-    );
+            _buildControls(context, controller),
+          ],
+        ),
+      );
+    }
+    else {
+      return new Container(
+        child: new Stack(
+          children: <Widget>[
+            new Container(
+              height:48.0,
+              width:double.infinity,
+              child: new VideoPlayer(controller),
+            ),
+            _buildControls(context, controller),
+          ],
+        ),
+      );
+    }
   }
 
   Widget _buildControls(
@@ -94,6 +120,7 @@ class _VideoPlayerWithControlsState extends State<PlayerWithControls> {
                 fullScreen: widget.fullScreen,
                 progressColors: widget.materialProgressColors,
                 autoPlay: widget.autoPlay,
+                hasVideo: widget.showVideoBox,
               )
             : new CupertinoControls(
                 backgroundColor: new Color.fromRGBO(41, 41, 41, 0.7),
@@ -103,6 +130,7 @@ class _VideoPlayerWithControlsState extends State<PlayerWithControls> {
                 fullScreen: widget.fullScreen,
                 progressColors: widget.cupertinoProgressColors,
                 autoPlay: widget.autoPlay,
+                hasVideo: widget.showVideoBox,
               )
         : new Container();
   }

from chewie.

jeffmikels avatar jeffmikels commented on June 6, 2024

I agree that a full-fledged audio player app should allow for sleep timers, background playing, etc, but I also think that Flutter needs a simple "plug and play" solution for media.

I'd like to see the video_player and audioplayer plugins get merged into a unified API so that media handling is as easy as image handling. The plugin should provide for accelerated playback, background playback, etc, and then plugins like chewie can focus on the display side of things.

Bottom line, I'm using chewie for this because the API is well-designed and because the visual controls are already there. I don't want to reinvent a wheel that just needs to be polished!

Thanks for your consideration anyway.

from chewie.

cbenhagen avatar cbenhagen commented on June 6, 2024

What do you think @brianegan & @jeffmikels, should we leave this open?

from chewie.

brianegan avatar brianegan commented on June 6, 2024

Hey there -- I'm sympathetic to the original goal, but I still feel Chewie is the wrong tool for audio playback since it relies on video_player, and I don't think we should support it.

from chewie.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.