Open wlingf opened 1 year ago
Same problem here
having same problem.
I found a solution thanks to chatGBT
class VideoCache {
late final Directory cacheDir;
/// Whenever this class is doing a download operation, this will be called
final Function(int bytesRecieved, int bytesLeft)? onReceiveBytes;
/// Whenever a download operation is completed, this will be called!
final VoidCallback? downloadCompleted;
final VoidCallback? onDownloadOperationCanceled;
final VoidCallback? onDownloadStart;
CancelToken cancelToken = CancelToken();
bool _disposed = false;
VideoCache({
this.onReceiveBytes,
this.downloadCompleted,
this.onDownloadOperationCanceled,
this.onDownloadStart,
});
/// Must be called ONCE, before using any method!
init() async {
cacheDir = await getTemporaryDirectory();
if (kDebugMode) {
print("INITIALIZED INSTANCE OF VIDEO CACHE");
}
}
Future<File?> getVideoThumbnail(String outPath, String url) async {
final arguments = [
'-i',
url,
'-ss',
'00:00:01.000',
'-vframes',
'1',
'-q:v',
'50',
outPath
];
final flutterFFmpeg = FlutterFFmpeg();
final execution = await flutterFFmpeg.executeWithArguments(arguments);
if (execution == 0) {
return File(outPath);
} else {
print('Error extracting video thumbnail');
return null;
}
}
Future<ImageProvider> getCachedVideoThumbnail(String url) async {
final filename = url.split('/').last;
final usableFileName = _generateUniqueKeyName(filename);
const determinedExtension = 'jpg';
final file = File('${cacheDir.path}/$usableFileName.$determinedExtension');
print(file.path);
if (file.existsSync()) {
return FileImage(file);
} else {
try {
print('Thumbnail not cached, trying to download');
final thumbnailFile = await getVideoThumbnail(file.path, url);
return (thumbnailFile != null
? FileImage(thumbnailFile)
: const AssetImage('assets/images/default-fallback-media.png'))
as ImageProvider;
} catch (e) {
print('Error downloading video thumbnail: $e');
return const AssetImage('assets/images/default-fallback-media.png');
}
}
}
void clearCache() async {
try {
await cacheDir.delete(recursive: true);
await cacheDir.create();
} catch (e) {
print('Error clearing video cache: $e');
}
}
String _determineVideoExtension(String name) {
if (name.contains('.avi')) {
return 'avi';
}
return 'mp4';
}
/// generates a key, from ANY string.
String _generateUniqueKeyName(String input) {
var bytes = utf8.encode(input); // Convert the input string to bytes
var digest = sha256.convert(bytes); // Generate the SHA-256 hash
var base64Url =
base64UrlEncode(digest.bytes); // Encode the hash as Base64 URL
return base64Url.substring(
0, 32); // Return the first 32 characters of the encoded string
// Encode the key using URL-safe Base64
}
/// fetch the video
Future<File?> fetchVideoFromCacheIfAny(String url) async {
File file = _generateFileWithCorrectNamingFromUrl(url);
print(file.path);
if (file.existsSync()) {
return file;
} else {
try {
onDownloadStart?.call();
final response = await Dio().get(url,
options: Options(responseType: ResponseType.bytes),
cancelToken: cancelToken,
onReceiveProgress: onReceiveBytes);
final downloadedFile = File(file.path);
await downloadedFile.writeAsBytes(response.data as List<int>);
downloadCompleted?.call();
return file;
} catch (e) {
if (e is CancelToken) {}
if (!_disposed) {
onDownloadOperationCanceled?.call();
}
cancelToken = CancelToken();
print('Error downloading video: $e');
return null;
}
}
}
File _generateFileWithCorrectNamingFromUrl(String url) {
final filename = url.split('/').last;
final usableFileName = _generateUniqueKeyName(filename);
final determinedExtension = _determineVideoExtension(filename);
final file = File('${cacheDir.path}/$usableFileName.$determinedExtension');
return file;
}
bool doesUrlFileExistInCache(String url) {
File file = _generateFileWithCorrectNamingFromUrl(url);
return file.existsSync();
}
cancelDownloadOperation() {
cancelToken.cancel();
}
dispose() {
print("DISPOSED OF: VIDEO CACHE INSTANCE! & CANCELED ON GOING OPERATIONS");
_disposed = true;
cancelToken.cancel();
}
}
The solution for me was to run in release mode in Android, debug mode did not work. While in iOS debug works fine.
Facing the same issue v0.5.3
Same issue here on v0.5.3
facing the same issue in v0.5.3
facing the same issue in v0.5.3
Just adding to the list here.
Same here v0.5.3
same here v0.5.3
same here. Any workarounds?
same here. Any workarounds?
worked with me only in https links
Hey Guys, The problem is when u call thumbnailFile
requires the thumbnailPath argument. You may ignore it since it was marked as optional. But in native side the code was designed in a way that it expecting the thumbnailPath argument and there is no null check or fallback. So thats why u may get MissingException Error.. I got that and fixed by providing thumbNailPath as getTemporaryDirectory() (you can give other dirs as well)
Hey Guys, The problem is when u call
thumbnailFile
requires the thumbnailPath argument. You may ignore it since it was marked as optional. But in native side the code was designed in a way that it expecting the thumbnailPath argument and there is no null check or fallback. So thats why u may get MissingException Error.. I got that and fixed by providing thumbNailPath as getTemporaryDirectory() (you can give other dirs as well)
Even if this parameter “thumbnailPath” is added, an error will still be reported
same here v0.5.3
android\app\src\main\AndroidManifest.xml, add this in application
this:
android:usesCleartextTraffic="true"
android\app\src\main\AndroidManifest.xml,将其添加到应用程序中
这:
android:usesCleartextTraffic="true"
this works for me
android\app\src\main\AndroidManifest.xml, add this in application
this:
android:usesCleartextTraffic="true"
Worked for me too. Except that this line is very dangerous. It makes your app use http instead of https. This means that it lowers the security significantly and allows Man in the Middle Attacks, spying, and other security concerns.