Flutter: Is the sound really recorded in the designated file? - flutter

Recently I am using a package named flutter_sound v9.1.7. Here are some of the codes.
String _mPath = 'tau_file.mp4';
Codec _codec = Codec.aacMP4;
File? file;
FlutterSoundPlayer? _mPlayer = FlutterSoundPlayer();
FlutterSoundRecorder? _mRecorder = FlutterSoundRecorder();
void record() async {
_mRecorder!
.startRecorder(
toFile: _mPath,
codec: _codec,
audioSource: AudioSource.microphone,
)
.then((value) {});
setState(() {
recording = true;
});
}
I have succeeded in recording and playing audio, but when I finish recording and try to analyze the seeming audio file tau_file.mp4, such like get the length of the file, an error occurred:
Cannot retrieve length of file, path = 'tau_file.mp4' (OS Error: No such file or directory, errno = 2).
The analysis code is here:
file = File(_mPath);
print(file?.path);
print(file?.absolute);
print(file?.length.toString());
I tried to seek answer in source codes, but only found an interface... So is the audio really be written to the file tau_file.mp4? Or maybe the process of analysis is wrong?
This is the first time that I use flutter_sound. Thanks for your help.

void stopRecorder() async {
await _mRecorder!.stopRecorder().then((value) {
setState(() {
//var url = value;
recordedUrl = value;
debugPrint('path : -------- $recordedUrl');
_mplaybackReady = true;
});
});
}
This is your recorded files url, when you stop the record you can get it.
The document includes this code. It gives you //var url = value;. Then you can handle it. like var recordedFile = File(url);. it's not a temporary one. You can upload it somewhere or whatever you like.

Related

Flutter Image form Image Picker to Document Path

I am creating an app that saves images locally through sqflite, I have soon found out that the images are being saved as temp which means that it will be deleted by the device and i'm not able to retrieve those images anymore. I have been coding to save it to the document directory of the app but it seems to fail and throw error
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FileSystemException: Cannot copy file to '/data/user/0/com.example.e4psmap/cache/scaled_0d5d5070-70da-4f42-9055-c31a6ed8d3d51761448072222030817.jpg', path = '/data/user/0/com.example.e4psmap/app_flutter/scaled_0d5d5070-70da-4f42-9055-c31a6ed8d3d51761448072222030817.jpg' (OS Error: No such file or directory, errno = 2)
this is my code:
void getpic(ImageSource src) async{
Uint8List byte;
final picfile = await _imagepicker.getImage(
source: src, imageQuality: 25
);
if(picfile != null){
Directory appDir = await getApplicationDocumentsDirectory();
String appdoc = appDir.path;
final filename = path.basename(picfile.path);
final local = File('${appdoc}/$filename');
final lclfile = await local.copy(picfile.path);
}
// converted = picfile!.path;
// setState(() {
// _imgfile = picfile!;
// });
Navigator.pop(context);
}
Anyone knows why I am having this errors, and any fix for this error, Thank you
The copy() function expects the source file to be passed as an argument, but in your code, you're passing picfile.path instead of the File object.
try to replace local.copy(picfile.path) with picfile.saveTo(local.path), which should save the image to the desired directory.
If you replace final with the corresponding class, the error will be very obvious.

Flutter video_compress and then ffmpeg trim video to 30s fails with endless logs

I am trying to make a simple app in Flutter. A user can either take or pick a video and then upload it. However, I wanted to compress the video for storage purposes on firebase storage, and also trim it to only get the first 30 seconds.
I am facing a very puzzling problem. I am able to compress the video, but with the resultant file, FFmpeg fails to trim it and I get endless logs which result in me having to stop the app and re-run. Alternatively, I am able to trim the video, but with the resultant file, I am unable to compress it getting the error: Failed to open file '/data/user/0/live.roots.roots/app_flutter/TRIMMED.mp4'. (No such file or directory) PlatformException(error, java.io.IOException: Failed to instantiate extractor., null, java.lang.RuntimeException: java.io.IOException: Failed to instantiate extractor.
This is my code below:
//! function that controls file compression and trimming
static Future<File> compressFile(File file) async {
print('[COMPRESSING FILE]');
String mimeStr = lookupMimeType(file.path);
var fileType = mimeStr.split('/');
if (fileType.contains("image")) {
print('[COMPRESSING FILE] - file is image');
String tempPath = (await getTemporaryDirectory()).path;
String targetPath = '$tempPath/${DateTime.now().toIso8601String()}.jpg';
return await compressImageAndGetFile(file, targetPath);
} else {
print('[COMPRESSING FILE] - file is video');
final compressedVideoFile = await compressVideoAndGetFile(file);
print('[VIDEO FILE COMPRESSED]');
return await trimVideoGetFile(compressedVideoFile);
}
}
//! function to compress video
static Future<File> compressVideoAndGetFile(File file) async {
print('[COMPRESSING VIDEO]');
var result = await VideoCompress.compressVideo(
file.absolute.path,
quality: VideoQuality.DefaultQuality,
deleteOrigin: true,
);
print('[COMPRESSED VIDEO TO]: ${result.file.path}');
return result.file;
}
//! function to trim video
static Future<File> trimVideoGetFile(File file) async {
print('[TRIMMING VIDEO]');
Directory appDocumentDir = await getApplicationDocumentsDirectory();
String rawDocumentPath = appDocumentDir.path;
String outputPath = rawDocumentPath + "/TRIMMED.mp4";
final newFile = File(outputPath);
if (await newFile.exists()) {
await newFile.delete();
}
_flutterFFmpeg
.execute(
"-ss 00:00:00 -i ${file.path} -to 00:00:30 -c copy $outputPath")
.then((rt) async {
print('[TRIMMED VIDEO RESULT] : $rt');
if (rt == -1) {
throw Exception("Something went wrong when trimming the video");
}
});
return File(outputPath);
}
Thank you in advance
Video_compress package allows you to trim the duration without the need to FFmpeg.
var result = await VideoCompress.compressVideo(
file.absolute.path,
quality: VideoQuality.DefaultQuality,
deleteOrigin: true,
startTime: 0, // customize start time
duration: 30, // customize the length
);

How to record a video with Camera Plugin in flutter?

I have this page where the camera is initialized and ready with a button that will record and stop the video, so I tried this :
FlatButton(
onPressed: () => {
!isRecording
? {
setState(() {
isRecording = true;
}),
cameraController.prepareForVideoRecording(),
cameraController.startVideoRecording('assets/Videos/test.mp4')
}
: cameraController.stopVideoRecording(),
},
............
but throws this error : nhandled Exception: CameraException(videoRecordingFailed, assets/Videos/test.mp4: open failed: ENOENT (No such file or directory)).
I don't understand, I don't want to open this file I want to save it there, Is there sth wrong with my code ?
In the new version, static method startRecordingVideo doesn't take any string parameter.
When you want to start the recording just see whether a video is already getting recorded, if not start
if (!_controller.value.isRecordingVideo) {
_controller.startVideoRecording();
}
and when you want to finish the recording you can call the static method stopVideoRecording() and it will give you a object of the class XFile, it will have the path to your video.
if (_controller.value.isRecordingVideo) {
XFile videoFile = await _controller.stopVideoRecording();
print(videoFile.path);//and there is more in this XFile object
}
This thing has worked for me. I am new to flutter please improve my answer if you know more.
You are trying to save a video in your assets folder which is not possible ,
What you need to do is to save to device locally either common folders like downloads or app directory.
Here is an example of how to go about it
dependencies:
path_provider:
Flutter plugin for getting commonly used locations on host platform
file systems, such as the temp and app data directories.
We will be saving the video to app directory.
We need to get the path to the directory where the file is or will be. Usually a file is put in the application's document directory, in the application's cache directory, or in the external storage directory. To get the path easily and reduce the chance of type, we can use PathProvider
Future<String> _startVideoRecording() async {
if (!controller.value.isInitialized) {
return null;
}
// Do nothing if a recording is on progress
if (controller.value.isRecordingVideo) {
return null;
}
//get storage path
final Directory appDirectory = await getApplicationDocumentsDirectory();
final String videoDirectory = '${appDirectory.path}/Videos';
await Directory(videoDirectory).create(recursive: true);
final String currentTime = DateTime.now().millisecondsSinceEpoch.toString();
final String filePath = '$videoDirectory/${currentTime}.mp4';
try {
await controller.startVideoRecording(filePath);
videoPath = filePath;
} on CameraException catch (e) {
_showCameraException(e);
return null;
}
//gives you path of where the video was stored
return filePath;
}

Converting Image FlutterWebImagePicker Output to File

I'm using Flutter web for a webapp and having trouble converting an image from the image picker to a file in order to upload it to my server. I display the image in Image.file(xxx) but I get the error:
Error while trying to load an asset: FormatException: Illegal scheme
character (at character 6)
Image(image:%20MemoryImage(Uint8List%234267a,%20scale:%201),%20frameBuilder...
Here is the code I'm trying:
Future getImage(bool isCamera) async {
Image image;
if (isCamera) {
image = await FlutterWebImagePicker.getImage;
} else {
}
var bytes = await rootBundle.load('$image');
String tempPath = (await getTemporaryDirectory()).path;
File file = File('$tempPath/profile.png');
await file.writeAsBytes(
bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes));
setState(() {
currentSelfie = file;
_accDetails['customer_selfie'] = currentSelfie;
});
}
Thanks in advance
I've tested this package and was very happy with the result imagePickerWebit returns 3 different types it can be in the form of Image(widget for preview), byte, File(upload)
then you can use this to get the values
html.File _cloudFile;
var _fileBytes;
Image _imageWidget;
Future<void> getMultipleImageInfos() async {
var mediaData = await ImagePickerWeb.getImageInfo;
String mimeType = mime(Path.basename(mediaData.fileName));
html.File mediaFile =
new html.File(mediaData.data, mediaData.fileName, {'type': mimeType});
if (mediaFile != null) {
setState(() {
_cloudFile = mediaFile;
_fileBytes = mediaData.data;
_imageWidget = Image.memory(mediaData.data);
});
}
I havent used the plugin although your code has 2 issues. One is the if statement and the second one is using Rootbundle. If you are picking from the filesystem, my assumption isCamera would be false. You have not added any logic for the falsy condition.
if (isCamera) {// This would be true if the source was camera
image = await FlutterWebImagePicker.getImage;
} else {
}
Additionally,
var bytes = await rootBundle.load('$image');
From the flutter documentation, rootbundle contains the resources that were packaged with the application when it was built. Those are assets that you define in your pubspec. yaml. You are selecting an image at runtime hence its not bundled as an asset.
Since the package appears to return an image object, use the toByteData method on the image i.e
image = await FlutterWebImagePicker.getImage;
await image.toByteData();//This method has some parameters. Look into them

In Flutter, How to detect the completion of copying file?

I am beginner on Flutter.
I want to do this process,,,
1. save a image file.
2. read the property information of the saved image file.
below is the code for it.
// save a image file.
String mainDir = await getMainDirectory(widget.topic);
String path = mainDir + '/' + count.toString();
image.copy(path);
ImageProperties properties;
try {
// get the property information of the image file.
properties = await FlutterNativeImage.getImageProperties( path);
}
on PlatformException catch(e) {
print( e );
// try again ...
properties = await FlutterNativeImage.getImageProperties(
path);
}
When this code running, sometimes an error is occurred.
the error message is "file is not exist".
So, I have to call "getImageProperties()" function again, and I can get the property.
If I can detect the completion of the file copy, I can make these code better.
Is there any suggestion ?
You can use await to make sure image copy finish
final File newImage = await image.copy(path);