最近咱们希望Flutter技能在桌面端的运用能有所突破,所以笔者跨进了本不了解的桌面端运用领域。今天给大家分享下咱们是怎么让Flutter怎么辨认外接windows10媒体设备,而且完结视频流烘托和摄影;从
官方插件外界纹路
到platformVielinuxw实践
,都尝试了一遍,最终选择了webRtc
,整个预研手机淘宝进程好事多磨,学到了很多常识!
需求布景
需求是在win10和Android9的设备上支撑外接摄像头,可以进行实时拍摄,做一个类似相机的运用。
从技能流程上来分析,咱们需求辨认出相机设备,拿到媒体流信息然后做烘托(烘托机制一般经过外接纹路Texture
去完结),最终捕获帧进行摄影/录制。Fandroid是什么系统lutter中,任何目标烘托后自然能拿android手机到RanderObject,只要有RanderObject这个实在linux的烘托目标,咱们就能进行相片的存储。
以上流程,理论上库现已帮咱们做好,可是桌面端的生态,往往没那么简略~~~
一、官方Plugin
Android端运用camera,windows运用camera_windows。官方的库对于内置相机的支撑做的很不错,直接引证后在手机和普通电脑上作用都很好;可是两个库都是明确不支撑外接设备,见issus-1、isLinuxsus-android的drawable类2,优先级分别是P4、P5,明显官方以为这些问题优先级不高。
而纵观整手机怎么定位别人手机个Flutter生态对USB外设的支撑,并没有一个官方的库,pub上的基本也是良莠不齐,大多只支撑单一渠道。
完结原理
- Android端的
cameralinux常用命令
插件,运用原生Camera2 Api,经过TextureRegistry创立纹路,然后Flutter用Texture进行制作。
- 创立相机实例,返回
textureId
// camera_android-0.9.8+3libsrcandroid_camera.dart
@override
Future<int> createCamera(
CameraDescription cameraDescription,
ResolutionPreset? resolutionPreset, {
bool enableAudio = false,
}) async {
try {
final Map<String, dynamic>? reply = await _channel
.invokeMapMethod<String, dynamic>('create', <String, dynamic>{
'cameraName': cameraDescription.name,
'resolutionPreset': resolutionPreset != null
? _serializeResolutionPreset(resolutionPreset)
: null,
'enableAudio': enableAudio,
});
return reply!['cameraId']! as int;
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}
- 预览控件返回Flutter Texturelinux重启命令 Widget,与原生返回的纹路id形成绑定,然后接纳纹路信linux系统息然后制作
// camera_android-0.9.8+3libsrcandroid_camera.dart
@override
Widget buildPreview(int cameraId) {
return Texture(textureId: cameraId);
}
- Android端经过
TextureRegistwindows更新有必要吗ry
创立createSurfaceTexture
,把textureId返回到Dart层。
// camera_android-0.9.8+3androidsrcmainjavaioflutterpluginscameraMethodCallHandlerImpl.java
private void instantiateCamera(MethodCall call, Result result) throws CameraAccessException {
String cameraName = call.argument("cameraName");
String preset = call.argument("resolutionPreset");
boolean enableAudio = call.argument("enableAudio");
TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture =
textureRegistry.createSurfaceTexture();
DartMessenger dartMessenger =
new DartMessenger(
messenger, flutterSurfaceTexture.id(), new Handler(Looper.getMainLooper()));
CameraProperties cameraProperties =
new CameraPropertiesImpl(cameraName, CameraUtils.getCameraManager(activity));
ResolutionPreset resolutionPreset = ResolutionPreset.valueOf(preset);
camera =
new Camera(
activity,
flutterSurfaceTexture,
new CameraFeatureFactoryImpl(),
dartMessenger,
cameraProperties,
resolutionPreset,
enableAudio);
Map<String, Object> reply = new HashMap<>();
reply.put("cameraId", flutterSurfaceTexture.id());
result.success(reply);
}
值得一提的是Flutter3.0后,官方的原生linux虚拟机制作方法现已抛弃了VirtualDisplay
,拥抱TextureLayer
,功能上现已优化了不少,让Flandroid是什么手机牌子utter的音视频烘托才能提升了不少。 但问题就是在instantlinux虚拟机iateCamera
之前,官方在Camera2的完结上,没有对外界设备进行处理,然后查找不到对应的外接相机接口类型。
- Windows端的完结彻底相同,都是经过
Texture
做烘托,原因也是获取相机列表的时分没有做外接设备的完结,这里不在赘述。
解决计windows许可证即将过期怎么办划
根据多端的camera接口做处理,把外设设备的逻手机搬家辑加上,应该就可以了。 在Texture纹路这块官方的完结是没有问题的。
当然这个思路我目前只停留在理论层面
,并未真实去完结,原因如下:
- 两个库android手机都是设计原生常识,咱们维护成本会很大;
- 官方的库维护的很频频,后面更多优化还得看官方,很有android平板电脑价格可能哪个版别就得悉数推翻重新来一遍。
二、PlatformView
明确一个观点,这个计划不可落地。预研这个计linux系统安装划的原因是咱们自身现已有原生的代码接口是什么封装,根据CameraX的Android完结,我只需求在Plugin上注册下视图即可,具体完结代码如下:
- 注册视图
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
val key: String = "camera"
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "camera_plugin")
channel.setMethodCallHandler(this)
CameraInfoManager.getCameraInfoList().forEach {
Log.d(TAG, "onAttachedToEngine: $it")
}
// 注册视图
flutterPluginBinding.platformViewRegistry.registerViewFactory(
key,
CameraFactory(flutterPluginBinding.binaryMessenger)
)
}
- 视图工厂
class CameraFactory(private val messenger: BinaryMessenger) :
PlatformViewFactory(StandardMessageCodec.INSTANCE) {
override fun create(context: Context?, id: Int, args: Any?): PlatformView {
return CameraPlatformView(context!!)
}
}
- 引进CameraX视图
class CameraPreView(context: Context, attrs: AttributeSet?) :
LinearLayout(context, attrs), LifecycleOwner {
private var camera: PreviewView
private val mLifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
init {
val view: View = LayoutInflater.from(context).inflate(R.layout.layout_camera_preview, this)
camera = view.findViewById(R.id.camera_preview_view)
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
// 这里是封装好的CameraX预览视图
CameraXPreview
.bindLifecycle(this)
.setPreviewView(camera)
.setCameraId(0)
.startPreview(context)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
}
override fun getLifecycle(): Lifecycle = mLifecycleRegistry
}
问题清楚明了,Flutter引擎发动白屏300ms,视图同步产生延时,内存平均新windows11有必要升级吗增20M+,而且接口英文视图生命周期没法同手机耗电速度过快怎么办步,都是致命问题。
根据上面的实践,Windows上咱们没有再做尝试了,Fail接口自动化。
三、webRtc
上面两种计划都以失败告终后,大接口英文佬提到了webRlinux必学的60个命令tc,从基础协议出发,往往能解决核心问题。所以flutter_webrtc上场,WebRTC供给音视频的收集、编解码、网络传输、显示等功用,而且还支撑跨渠道:接口crc错误计数windows,linux,mac,android,现已被纳入被纳入W3C推荐标准。webRtc开发文档
- 引证
fllinux必学的60个命令utter_webrlinux系统tc
这个库,其烘托原理依旧是外接纹路,运用linux重启命令方法查看官方的example实例即可; - 重手机号最旺财的尾数点在完结摄影功用,摄影无非就是进行帧捕获,Android现已完结:
final videoTrack = localStream!
.getVideoTracks()
.firstWhere((track) => track.kind == 'video');
final frame = await videoTrack.captureFrame();
// 运用image.memory即可烘托
frameList = frame.asUint8List();
- 而windows端很遗憾,还没有完结摄影功用,见issus;所以我想到了曲线救国,经过
截取屏幕来保存图像
。由所以运用Texture烘托,通常的RenderRepaintBoundary
+GlobalKey
是没办法拿到RanderObject的!
幸亏插件供给了截取屏幕的方法,也算完结曲线救国了。
try {
var sources = await desktopCapturer.getSources(types: [SourceType.Window]);
DesktopCapturerSource capture =
sources.firstWhere((element) => element.name == 'my_camera');
// 运用image.memory即可烘托
frameList = capture.thumbnail;
return;
} catch (e) {
print(e.toString());
}
写在最终
到此,崎岖的外接相机预研之路告一段落。可是功能比起原生,真的差了一截,这让咱们意识到,在官方不支撑外接设备之前,针对此类需求接口是什么,还是少用Flutter来完结。
Flutter桌面运用尽管发布了Stable版别,但接口说句实话生态确实比移动端差了不少,这意味着咱们需求一起建设这接口英文个生态,可是趋势起来了,咱们也愿意社区共建!
另外插个题外话,关于上面windows截取屏幕的需求,其实是有issus未封闭的,7月1号下午刚参加了issue的讨论,傍晚作者就拉了pull requesAndroidt,而且更了一版,解了当务之急啊Windows!!!
怎么说呢,开源万岁,Respect!