Nei*_*fen 6 video video-thumbnails web flutter
出于性能原因,我一直在尝试为上传到 Firebase Firestore 的视频列表创建缩略图。
我想了不同的方法来解决这个问题。但我还没有找到实际可行的解决方案。给我最大希望的一个解决方案是第 5 个,所以请继续关注;)
有许多缩略图包,例如video_thumbnail,但该包无法在网络上运行。
我想也许从视频创建一个 gif,然后导出单个帧,但我发现执行此操作的所有包也无法在网络上工作(flutter_video_compress、flutter_ffmpeg
也许我可以制作一个 1 秒版本的视频,所以我考虑修剪视频,结果相同。我发现的软件包不支持网络(video_trimmer,video_editor)
我发现有一个截图包。所以我尝试了 video_player 和 HtmlElementView。两者的结果相同。这是代码:
import 'dart:html';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:screenshot/screenshot.dart';
...
Widget build(BuildContext context) {
if (widget.item.thumbnail != null) {
return Image.network(widget.item.thumbnail!);
}
//This is my video's path
String path = widget.path;
VideoElement video;
ScreenshotController screenshotController = ScreenshotController();
// ignore:undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(url, (int viewId) {
// just making sure I don't have some weird issues with crossOrigins
video = VideoElement()..crossOrigin = 'anonymous';
// Here I make sure, that the video is ready to play and I seek the first frame
video.onCanPlay.listen((event) {
_video.currentTime = 1;
});
// Here I make sure, that the video is actually showing a frame
video.onSeeking.listen((event) async {
var capture = await screenshotController.capture();
DaysService.exportThumbnail(capture);
});
video.src = path;
return video;
});
return Screenshot(
controller: screenshotController,
child: HtmlElementView(
viewType: path,
),
);
}
Run Code Online (Sandbox Code Playgroud)
但我有一个很大的例外,据我了解是因为我无法在网络上截图?(我想这也是为什么这些缩略图包都不能在网络上工作的原因)。这是异常堆栈:
Error: Unexpected null value.
at Object.throw_ [as throw] (http://localhost:58128/dart_sdk.js:5061:11)
at Object.nullCheck (http://localhost:58128/dart_sdk.js:5388:30)
at _engine.PlatformViewLayer.new.preroll (http://localhost:58128/dart_sdk.js:137129:12)
at _engine.OffsetEngineLayer.new.prerollChildren (http://localhost:58128/dart_sdk.js:136513:15)
at _engine.OffsetEngineLayer.new.preroll (http://localhost:58128/dart_sdk.js:136788:35)
at _engine.OffsetEngineLayer.new.prerollChildren (http://localhost:58128/dart_sdk.js:136513:15)
at _engine.OffsetEngineLayer.new.preroll (http://localhost:58128/dart_sdk.js:136788:35)
at _engine.TransformEngineLayer.new.prerollChildren (http://localhost:58128/dart_sdk.js:136513:15)
at _engine.TransformEngineLayer.new.preroll (http://localhost:58128/dart_sdk.js:136788:35)
at _engine.RootLayer.new.prerollChildren (http://localhost:58128/dart_sdk.js:136513:15)
at _engine.RootLayer.new.preroll (http://localhost:58128/dart_sdk.js:136508:31)
at _engine.LayerTree.new.flatten (http://localhost:58128/dart_sdk.js:137408:22)
at _engine.LayerScene.new.toImage (http://localhost:58128/dart_sdk.js:137170:36)
at layer$.OffsetLayer.new.toImage (http://localhost:58128/packages/flutter/src/rendering/layer.dart.lib.js:1395:30)
at toImage.next (<anonymous>)
at runBody (http://localhost:58128/dart_sdk.js:38659:34)
at Object._async [as async] (http://localhost:58128/dart_sdk.js:38690:7)
at layer$.OffsetLayer.new.toImage (http://localhost:58128/packages/flutter/src/rendering/layer.dart.lib.js:1386:20)
at proxy_box.RenderRepaintBoundary.new.toImage (http://localhost:58128/packages/flutter/src/rendering/proxy_box.dart.lib.js:3158:26)
at screenshot.ScreenshotController.new.<anonymous> (http://localhost:58128/packages/screenshot/screenshot.dart.lib.js:162:39)
at Generator.next (<anonymous>)
at runBody (http://localhost:58128/dart_sdk.js:38659:34)
at Object._async [as async] (http://localhost:58128/dart_sdk.js:38690:7)
at http://localhost:58128/packages/screenshot/screenshot.dart.lib.js:150:68
at http://localhost:58128/dart_sdk.js:33300:33
at internalCallback (http://localhost:58128/dart_sdk.js:25436:11)
Run Code Online (Sandbox Code Playgroud)
@override
Widget build(BuildContext context) {
if (widget.item.thumbnail != null) {
return Image.network(widget.item.thumbnail!);
}
//this is my video's path
String path = widget.path;
VideoElement video;
// ignore:undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(path, (int viewId) {
video = document.createElement('video') as VideoElement;
// just making sure I don't have some weird issues with crossOrigins
video.crossOrigin = 'anonymous';
// Here I make sure, that the video is ready to play and I seek the first frame
video.onLoadedMetadata.listen((event) {
video.currentTime = 1;
});
// Here I make sure, that the video is actually showing a frame
video.onSeeking.listen((event) async {
var canva = document.createElement('canvas') as CanvasElement;
canva
..height = video.videoHeight
..width = video.videoWidth;
canva.context2D..drawImage(video, video.videoWidth, video.videoHeight);
var data = Uri.parse(canva.toDataUrl()).data;
DaysService.exportThumbnail(data?.contentAsBytes());
});
video.src = path;
return video;
});
//I also still show the video. The endgoal would be to show the Thumbnail tho
return HtmlElementView(
viewType: path,
);
}
Run Code Online (Sandbox Code Playgroud)
结果是一张具有正确纵横比的灰色图片。我不知道为什么它是灰色的,我几乎觉得我做错了什么,而不是因为它是网络所以这是不可能的。
如果您知道我如何解决我的解决方案,或者您有其他想法,请告诉我:)
小智 1
你可以试试ffmpeg_wasm
打包。它是ffmpeg_wasm
.
首先,您必须初始化并加载 ffmpeg。
FFmpeg ffmpeg = createFFmpeg(true, "https://unpkg.com/@ffmpeg/core@0.11.0/dist/ffmpeg-core.js");
void loadFFmpeg() async {
await promiseToFuture(ffmpeg.load());
}
Run Code Online (Sandbox Code Playgroud)
您可以在访问任何函数之前确保 ffmpeg 是否已加载ffmpeg.isLoaded();
。
当您选择一个文件时,首先需要将该文件写入内存。
ffmpeg.writeFile(
'writeFile', 'input.mp4', filePickerResult!.files.single.bytes);
Run Code Online (Sandbox Code Playgroud)
然后,对于这个特定的用例,您可以使用以下 ffmpeg 命令。
await promiseToFuture(ffmpeg.run7("-i", "input.mp4", '-vf',
'select=\'eq(n,0)\'', '-vsync', '0', 'frame1.webp'));
var firstFrameData = ffmpeg.readFile('readFile', 'frame1.webp');
Run Code Online (Sandbox Code Playgroud)
生成的firstFrameData 是html blob 文件。
Ps 我是那个包的作者。我也面临同样的问题。对于我的用例,我在部署时也遇到了 cors 错误,因此我需要下载 ffmpeg-core 和 canvaskit js 包并将其存储在 Web 文件夹中。
归档时间: |
|
查看次数: |
1543 次 |
最近记录: |