Flutter - Streaming and Caching videos - caching

I'm developing an application in flutter which is showing videos in a list (like Instagram). Videos must be streamed so I can't download them first and then play them.
I want to cache them while they are being streamed. I've seen CacheManager class but it will download the whole file and then pass it to video player to play it.
How can I implement a cache manager to show the video file while it is being downloaded to cache folder?

I might be writing this a bit late but just in case anybody looking for a solution soon.
By the moment the official video_player plugin doesn't support video caching over network yet.
But fortunately, there been some attempts by contributors to add caching feature to the video_player plugin
You can track updates and find another PRs here: https://github.com/flutter/flutter/issues/28094
Replace video_player in your pubspec.yaml with
video_player:
git:
url: https://github.com/sanekyy/plugins.git
ref: caching
path: packages/video_player/video_player
In case of you are using chewie or other libraries that depend on video_player plugin add:
dependency_overrides:
video_player:
git:
url: https://github.com/sanekyy/plugins.git
ref: caching
path: packages/video_player/video_player
And now to cache the video pass useCache : true to
_videoPlayerController = VideoPlayerController.network(videoURL, useCache: true);
By default both maxFileSize and maxCacheSize is set to 10 * 1024 * 1024 bytes.
To adjust the cache size:
VideoPlayerController.setCacheSize(100 * 1024 * 1024, 200 * 1024 * 1024);
Another Solution:
Is to stream the video normally using the official plugin and to cache the video file using flutter_cache_manager simultaneously.
But this will lead to fetch the video twice the first time (Once for streaming through the video_player, Another for downloading the video through the cachemanager)
Here how the scenario would goes:
1- Check with flutter_cache_manager if the video_url is already downloaded and cached.
2- if the video is cached, pass the file path to video_player VideoPlayerController.file(path), if not download the file using cachemanager and stream the video using VideoPlayerController.network(videoURL) (at this moment video is being fetched twice... by videoplayer and cachemanager).

Visit https://github.com/elgsylvain85/cachedflickvideoplayer.git
It is a video player for flutter. It combines both: The flick_video_player plugin for the base architecture, own set of UI and The cached_video_player plugin for cache supporting.
In your pubspec.yaml file :
cachedflickvideoplayer:
git:
url: https://github.com/elgsylvain85/cachedflickvideoplayer.git
a demo of code :
import 'package:cached_video_player/cached_video_player.dart';
import 'package:cachedflickvideoplayer/cachedflickvideoplayer.dart';
import 'package:cachedflickvideoplayer/controls/flick_landscape_controls.dart';
import 'package:cachedflickvideoplayer/controls/flick_video_with_controls.dart';
import 'package:cachedflickvideoplayer/manager/flick_manager.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class ViewPage extends StatefulWidget {
FlickManager flickManager;
ViewPage() {
flickManager = initVideo();
}
#override
_ViewPageState createState() => _ViewPageState();
FlickManager initVideo() {
return FlickManager(
cachedVideoPlayerController:
CachedVideoPlayerController.network('https://media.istockphoto.com/videos/blurred-motion-of-people-in-restaurant-blur-background-video-id1190840021'),
);
}
}
class _ViewPageState extends State<ViewPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: <Widget>[
Card(
margin: const EdgeInsets.fromLTRB(20, 20, 20, 100),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.all(8),
height: 300,
child: FlickVideoPlayer(
flickManager: widget.flickManager,
flickVideoWithControlsFullscreen:
FlickVideoWithControls(
videoFit: BoxFit.contain,
controls: FlickLandscapeControls(),
),
)),,
]),
),
],
));
}
#override
void dispose() {
super.dispose();
widget.flickManager.dispose();
}
}

You can mix video_player with flutter_cache_manager.
/// Get a file from the cache or download and insert it into the memory.
final url = 'link-to-the-file';
final file = await DefaultCacheManager().getSingleFile(url, key: url);
_videoController = VideoPlayerController.file(file)
..initialize().then(
(_) => initialize(),
);
As the result, if the manager does not find a file in the cache by url, it will download it, insert it into the memory and return the file object.
This solution is only effective if you work with small sizes video.

Related

Can't load image in stack in flutter

I want to load image in my app
in stack
but image not load
I don't have an error
I've add image in pubspec and pub it .
this is part of my code :
InkWell(
child: Stack(
children: <Widget>[
new Image.asset('assets/Images/b.jpg',fit: BoxFit.cover,),
Center(child: Text("something",textAlign: TextAlign.center,)),
]
),
onTap: () {
ListOfEpisode();
print("am");
},
),
I've try it with network image but still not work.
anyone know that why i can't loaded ?
Change it towercase i:
new Image.asset('assets/images/b.jpg',fit: BoxFit.cover,),
In your pubespec you have it assets/images, in your code it's Images. Fix one of them.
Path in your directory and pubsec is:
assets/images/b.jpg
But in your code its:
assets/Images/b.jpg
change path in code to:
assets/images/b.jpg

Next.js Image component with external dynamic source

I was working on my Next.js project and while running it locally html img tag worked okay.
While building, I got a warning, to change it to Image component from Next.js
So I did, but now I get a warning:
Error: Invalid src prop (https://image.ceneostatic.pl/data/products/10813131/i-dixit.jpg) on next/image, hostname "image.ceneostatic.pl" is not configured under images in your next.config.js
See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
I read in the documentation that solution is to add a domain to next.config.js.
But 2 problems occurs to me here:
Even if I specify a domain like this, it doesn't work
module.exports = {
images: {
domains: ['image.ceneostatic.pl'],
},
};
I have my project connected to MongoDB, where are stored links to the images. What's more, I want an user to pass a link, while creating a new entry. So I don't want to have hard-coded domains, as I don't know which img an user will use.
Is there a way to omit domains list or a walk-around to use tag?
Thanks!
You can use something called next Loader via the following code:
import Image from 'next/image'
const myLoader = ({ src, width, quality }) => {
return `https://image.ceneostatic.pl/data/products/{src}/i-dixit.jpg`
}
var photoID = 10813131
const MyImage = (props) => {
return (
<Image
loader={myLoader}
src=photoID
width={500}
height={500}
/>
)
}
Your next.config.js:
module.exports = {
images: {
loader: 'imgix',
path: 'https://image.ceneostatic.pl',
},
}
All documentation is linked here.

Shell commands in Flutter

I am developing a desktop UI in Flutter and I need to create buttons to execute shell commands.
I already can execute some commands simple such as ls -l and it shows its results nicely in the console.
However I need a way to show the results in the main app and not in the console, I have tried the snackbar but it is not so nice and it does not get the outputs from other commands that gives dynamic outputs.
I would like to watch dynamic outputs such as tail -f and top.
How could I open a new window in the flutter app to show the execution of a command?
For now, I have this:
class LsButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
onPressed: () {
Process.run('ls', ['-l']).then((ProcessResult results) {
Flushbar(
title: "Output",
message: results.stdout,
duration: Duration(seconds: 15),
)..show(context);
});
},
child: Text('Show dir contents!',
style: TextStyle(
fontSize: 10,
),)
),
);
}}
Flutter doesn't yet support multiple windows, so currently if you want to do that you'd have to do it via native code, controlled via platform channels.

play audio in flutter

i made one demo in flutter its work fine in Android, iphone, linux desktop and mac desktop but in windows desktop it give me error
[ERROR:c:\b\s\w\ir\cache\builder\src\flutter\lib\ui\ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method stop on channel xyz.luan/audioplayers)
can any one help me to resolve this error?
in this demo i used audioplayers 0.14.2 to play local audio file in flutter.
here is my code:-
void main() {
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
runApp(new MaterialApp(home: new ExampleApp()));
}
class ExampleApp extends StatefulWidget {
#override
_ExampleAppState createState() => new _ExampleAppState();
}
class _ExampleAppState extends State<ExampleApp> {
AudioPlayer advancedPlayer;
AudioCache audioCache;
#override
void initState() {
super.initState();
initPlayer();
}
void initPlayer() {
advancedPlayer = new AudioPlayer();
audioCache = new AudioCache(fixedPlayer: advancedPlayer);
}
void playfirst() {
audioCache.play('audio1.mp3');
}
void stop() {
advancedPlayer.stop();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 1,
child: Scaffold(
appBar: AppBar(
title: Text('Audio file demo'),
),
body: Center(
child: Column(
children: <Widget>[
ButtonTheme(
minWidth: 48.0,
child: RaisedButton(child: Text("play"), onPressed: playfirst)),
ButtonTheme(
minWidth: 48.0,
child: RaisedButton(child: Text("stop"), onPressed: stop))
],
),
)
),
);
}
}
can any one help me to resolve this error?
The only way to resolve the error would be to write an implementation of that plugin for Windows; the reason it's telling you that the plugin is missing is that the plugin doesn't have Windows support (which you can tell because there's no windows folder in the plugin repository, or windows: entry in the pubspec.yaml).
its work fine in [...] linux desktop
That's surprising, given that the plugin you are using doesn't support Linux either.
It's unlikely that you're going to find a plugin that has Windows support at the moment given that the official documentation currently says:
Note: Windows and Linux plugin APIs and tooling are not yet stable, so any plugin written now will need frequent updates for breaking changes. Because of this, publishing Windows and/or Linux plugins to pub.dev at this stage is strongly discouraged.

How do I pass an Internationalization Object to Child Widgets in Flutter

Just getting started with Flutter/dart, transitioning for PHP, and struggling to figure out how to pass classes into widgets.
I am working on creating my first android and iOS applications using flutter.
I am working with internationalization and everything works fine at my initial build page using the internationalization class I have. However, when passing it on to another widget I get:
NoSuchMethodError: The getter textTitle was called on null.
Receiver: null
tried calling: textTitle
What is the best way of handling this?
Flutter Doctor
[✓] Flutter (Channel beta, v0.1.5, on Mac OS X 10.13.3 17D47, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.1)
[✓] Android Studio (version 3.0)
[✓] Connected devices (1 available)
Localization dart
class HnLocalizations{
HnLocalizations(this.locale);
final Locale locale;
static HnLocalizations of(BuildContext context){
return Localizations.of<HnLocalizations>(context, HnLocalizations);
}
static Map<String, Map<String, String>> _localizedValues = {
'en': {
'btnLabelLoginS1': 'Login',
'btnLabelRegisterS1': 'Sign Up'
},
;
String get s1ButtonLabelLogin =>
_localizedValues[locale.languageCode]['btnLabelLoginS1'];
class HnLocalizationsDelegate extends LocalizationsDelegate<HnLocalizations> {
const HnLocalizationsDelegate();
#override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
#override
Future<HnLocalizations> load(Locale locale) =>
new SynchronousFuture<HnLocalizations>(new HnLocalizations(locale)); //HnLocalizations.load(locale);
#override
bool shouldReload(HnLocalizationsDelegate old) => false;
}
Main Dart
void main() {
runApp(new MaterialApp(
localizationsDelegates: [
const HnLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'), /// Americans
const Locale('en', 'GB') /// Brits
],
title: 'HN',
home: new EntryPage(),
));
}
class EntryPage extends StatelessWidget {
final HnColors _hnColors = new HnColors();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
// !!!**** THIS WORKS AS EXPECTED ****!!!!
title: new Text(HnLocalizations.of(context).s1ButtonLabelLogin),
backgroundColor: _hnColors.transparent(),
elevation: 0.0,
),
backgroundColor: _hnColors.accent(),
body: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/Background_World.png"),
fit: BoxFit.fitWidth,
),
),
child: new PanelArea(),
)
);
}
}
class PanelArea extends StatelessWidget {
#override
Widget build(BuildContext context) {
HnColors _hnColors = new HnColors();
return new Container(
child: new Center(
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(15.0),
color: _hnColors.transparent()
),
child: new Column(
children: [
new Image.asset('assets/Icon_Intro_login'),
new Text(
// !!!**** ERROR IS HERE ****!!!!
HnLocalizations.of(context).s1M1HeaderTitle,
style: new TextStyle(
color: _haillioColors.white()
),
),
What is the best way of handling this?
Update: Mar 11 2018
I've discovered that if I move all of the code into the main.dart file. All localization works fine. However, when I move my widgets into a separate dart file, the errors come back, even though all of the code is the same.
Update: Mar 12 2018
nicolás-carrasco pointed in the right direction by a reference in this post (Thank you). The problem had to do with imports which is addressed in this post here which ended up being the solution that worked for me. The example is added below in answers.
Nicolás Carrasco pointed towards a solution which was related to what was causing the problem for me by way of link to this post.
In the localization.dart file imports I had:
import 'package:hn/hnLocalization.dart';
While in the main.dart file imports I had:
import 'hnLocalization.dart';
These are not the same thing as described here
Making sure that all files are imported using relative paths vs packages resolved the problem. The distinction is that my files, not the dependencies use relative path. That part stumped at first.
Now my localization.dart file has the following.
import 'hnLocalization.dart'; // <--- Using relative Path
class PanelArea extends StatelessWidget {
#override
Widget build(BuildContext context) { ...
child: new Column(
children: [
new Image.asset('assets/Icon_Intro_login'),
// This Now Works --->
new Text(HnLocalizations.of(context).s1M1HeaderTitle,
]
...
and all is right now.

Resources