the below stream method is triggered every frame
stream() async {
_isStreaming=true;
var counter=0;
channel = WebSocketChannel.connect(
Uri.parse('ws://192.168.11.8:8000/real-time/')
) as IOWebSocketChannel?;
_cameraController?.startImageStream((CameraImage img) async{
final imageBytes= await convertYUV420toImageColor(img);
if(_isStreaming) {
channel?.sink.add(imageBytes);
}
});
channel?.stream.listen((message) {
print(message);
var jsonDecodex = jsonDecode(message);
var prediction = jsonDecodex['prediction'];
var predictProba = jsonDecodex['predict_proba'];
_prediction = prediction;
_accuracy =predictProba+"%";
if(mounted) {
setState(() {});
}
},
);}
I'm working on a flutter app that opens a stream and sends every frame to a Django server via WebSockets, However, nearly after 1 minute of streaming 'out of memory' error happens.
Related
I'm currently facing an issue, where I'm trying to Save a large video file (586 Mb).
I'm able to download the entire file but, when I try to write this file to memory, I get an Error of “Out of memory”. It works for smaller video files like (80mb, 100 mb) but fails for the large files. I'm attaching the code snippet for reference.
Future download() async {
var request = http.Request('GET', Uri.parse(url!));
var response = httpClient.send(request).timeout(Duration(seconds: 3));
var chunks = <List<int>>[];
var downloaded = 0;
try{
response.asStream().listen((http.StreamedResponse r) {
if(r.statusCode==HttpStatus.ok){
r.stream.listen((List<int> chunk) {
// Display percentage of completion
chunks.add(chunk);
downloaded += chunk.length;
downloadingCallBack(downloaded / r.contentLength! * 100,filesize(downloaded),filesize(r.contentLength));
}, onDone: () async {
// Display percentage of completion
print('downloadPercentage: ${downloaded / r.contentLength! * 100}');
// Save the file
try{
var file = File('$dirPath/$fileName');
//The Uint8List below throws the error "Out of memory and I'm not able to write the file to memory"
***Error Here ==>*** final bytes = Uint8List(r.contentLength!); //Code fails here, (r.contentLength is 586900112 bytes)
var offset = 0;
for (var chunk in chunks) {
bytes.setRange(offset, offset + chunk.length, chunk);
offset += chunk.length;
}
await file.writeAsBytes(bytes);
downloadingDoneBack(true);
return;
}catch(fileException){
rethrow;
}finally{
httpClient.close();
}
});
}else{
downloadingDoneBack(false);
}
});
}catch(e){
downloadingDoneBack(false);
}finally{
httpClient.close();
}
}
Since it's a large file, I think it would be better to download your file using flutter_downloader plugin which also supports notifications and background mode.
Import and initialize flutter downloader
import 'package:flutter_downloader/flutter_downloader.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// Plugin must be initialized before using
await FlutterDownloader.initialize(
debug: true // optional: set to false to disable printing logs to console (default: true)
ignoreSsl: true // option: set to false to disable working with http links (default: false)
);
runApp(const MyApp())
}
Create new download task
final taskId = await FlutterDownloader.enqueue(
url: 'your download link',
savedDir: 'the path of directory where you want to save downloaded files',
showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);
Handle isolates
Important note: your UI is rendered in the main isolate, while download events come from a background isolate (in other words, codes in callback are run in the background isolate), so you have to handle the communication between two isolates. For example:
ReceivePort _port = ReceivePort();
#override
void initState() {
super.initState();
IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
_port.listen((dynamic data) {
String id = data[0];
DownloadTaskStatus status = data[1];
int progress = data[2];
setState((){ });
});
FlutterDownloader.registerCallback(downloadCallback);
}
#override
void dispose() {
IsolateNameServer.removePortNameMapping('downloader_send_port');
super.dispose();
}
static void downloadCallback(String id, DownloadTaskStatus status, int progress) {
final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port');
send.send([id, status, progress]);
}
Load all download tasks
final tasks = await FlutterDownloader.loadTasks();
This is the code which i used to fetch data from database
Future<List<ShadeColorDatabase>?> getShadeColorData() async {
Database? db = await instance.database;
try {
var data = await db!.query(table4);
List<ShadeColorDatabase>? shadeColorDataList = data.isNotEmpty
? data.map((e) => ShadeColorDatabase.fromMap(e)).toList()
: [];
return shadeColorDataList;
} catch (e) {
rethrow;
}
}
and i called this function in my screen like this
filterDatabaseData() async {
final databaseData = await DatabaseHelper.instance.getShadeColorData();
for (int i = 0; i < databaseData!.length; i++) {
print("${databaseData[i].colorName}");
setState(() {
allColorCodeList.add(databaseData[i].colorName);
});
}
}
#override
void initState() {
// TODO: implement initState
super.initState();
filterDatabaseData();
}
but i get this warning saying:- warning-database-has-been-locked-for-00010-000000-make-sure-you-always-use-th. this says when i run my app for the first time. Meaning if someone is running the app for the first time this warning is showing and related data is not showing is there any way i can fix this problem need some help. Thanks
I want to use flutter fulfilled a mqtt client. the client need send message to serve for loop.
I used "while" keyword for loop. but the flutter UI is pending during the while function.
if use isolate to work it, sending the cancel flag failed.
Does there anybody have the experience on it?
----------code------
onpressed -----> Future Function ----> use while loop---->the app pending cannot press anywhere---> the loop stop, the app recovery
I want start a mqtt client to send mqtt message for loop.
but when pressed the function, the while loop pended the app.
Expected results: the loop works in an async work, and the app can work rightly.
Actual results: the app is pending.
###UI
children: [
SizedBox(width: 200),
MaterialButton(
child: Text('发送'),
onPressed: () {
BtnsendMsg();
},
####onpressed function
mc = new MqttClient(false);
BtnsendMsg() async {
mc.MsgSend(clientid, topic, msgname, '3');
print("back");
}
####loop function
class MqttClient {
bool isStop;
MqttClient(this.isStop);
Future MsgSend(clientid, topic, msgname, interval) async {
isStop = false;
var cc = await clientGet(clientid);
var msg = await msgGet(msgname);
String host = "1.1.1.1";
String msgdata = "1111";
if (cc != null) {
host = cc.host!;
}
if (msg != null) {
msgdata = msg.msgdata!;
}
Future future = Future(() {
while (isStop == false) {
SendMsgOnce(host, clientid, topic, msgdata);
sleep(Duration(seconds: 3));
}
});
sleep(Duration(seconds: 30));
isStop = true;
}
This is because you are putting load on main thread by not using async and await while sending request to the server. Do the following changes to your code then it should get work.
class MqttClient {
bool isStop;
MqttClient(this.isStop);
Future MsgSend(clientid, topic, msgname, interval) async {
isStop = false;
var cc = await clientGet(clientid);
var msg = await msgGet(msgname);
String host = "1.1.1.1";
String msgdata = "1111";
if (cc != null) {
host = cc.host!;
}
if (msg != null) {
msgdata = msg.msgdata!;
}
Future future = Future(() async {
while (isStop == false) {
await SendMsgOnce(host, clientid, topic, msgdata);
sleep(Duration(seconds: 3));
}
});
sleep(Duration(seconds: 30));
isStop = true;
}
In your on pressed function you are using async but now awaiting for that
mc = new MqttClient(false);
BtnsendMsg() async {
await mc.MsgSend(clientid, topic, msgname, '3');
print("back");
}
I have stream like the below-mentioned code, here want to merge streams and wanted to call it one by one whenever it required.
main() {
Stream<String> stream = new Stream.fromFuture(getData());
stream.listen((data) {
print("DataReceived: "+data);
}, onDone: () {
print("Task Done");
});
}
Future<String> getData() async {
await Future.delayed(Duration(seconds: 5)); //Mock delay
print("Fetched Data");
return "This a test data";
}
onDone will be called after 5 seconds.
For it, StreamQueue can be used to combine multiple streams
Add Dependency:
async: ^2.4.1
Use StreamQueue:
void main() async {
Stream<String> stream1 = new Stream.fromFuture(getData(2));
Stream<String> stream2 = new Stream.fromFuture(getData(4));
Stream<String> stream3 = new Stream.fromFuture(getData(6));
var streams = StreamGroup.merge([stream1, stream2, stream3]);
var data = StreamQueue(streams);
var first = await data.next;
print(first);
var second = await data.next;
print(second);
var third = await data.next;
print(third);
var third1 = await data.next;
print(third1);
}
Future<String> getData(int duration) async {
await Future.delayed(Duration(seconds: duration)); //Mock delay
return "This a test data for duration $duration";
}
Output:
I/flutter ( 7950): This a test data for duration 2
I/flutter ( 7950): This a test data for duration 4
I/flutter ( 7950): This a test data for duration 6
data.next will provide you the first stream in Queue which is in our
case is stream1, here we can take the future value and use. stream.next gives next stream in the queue if nothing exists in queue & stream.next is performed then it will throw an exception.
I use audioplayers to listen to a radio channel (streaming) in Flutter. It works well in the background except when the user receives a call. In this case the playing stops but doesn't restart automatically at the end of the call.
AudioPlayer audioPlayer = new AudioPlayer();
const kUrl = "http://5.39.71.159:8865/stream";
Future play() async {
int result = await audioPlayer.play(kUrl);
setState(() {
playerState = PlayerState.playing;
});
}
Future stop() async {
int result = await audioPlayer.stop();
}
How can I put my radio in pause mode when a call comes and restart the playing at the end of the call?
Try this
audioPlayer.onPlayerStateChanged.listen((AudioPlayerState s) => {
print('Current player state: $s');
setState(() => palyerState = s);
});