Flutter摄像头切换插件switch_camera的使用
Flutter摄像头切换插件switch_camera的使用
switch_camera
是一个Dart库,它提供了与Rust交互的Dart FFI接口,用于摄像头和音频录制功能。它支持视频捕捉、帧流、视频写入以及音频录制,并且可以将视频与音频合并。我使用 switch_camera
库构建了一个名为Zed Camera的桌面应用程序,您可以在 YouTube 上观看其演示。该库在物联网(IoT)、闭路电视(CCTV)和工业环境中特别有用,在这些环境中多个摄像头输入和可靠的音视频记录至关重要。
功能
- 列出可用的摄像头设备
- 打开和释放摄像头设备
- 捕获视频帧(带翻转和不带翻转)
- 流式传输视频帧(带翻转和不带翻转)
- 开始视频写入
- 写入视频帧(带翻转和不带翻转)
- 音频录制(开始、停止、暂停、恢复)
- 合并音频和视频
平台支持
- Linux
安装
要安装 switch_camera
,请使用 flutter pub add
:
Flutter
flutter pub add switch_camera
依赖项
Linux - Ubuntu:
sudo apt-get update
- 获取 OpenCV:
sudo apt-get install libopencv-dev clang libclang-dev
- 安装 JACK 开发文件:
sudo apt-get install libjack-jackd2-dev
- 安装 ALSA 开发文件:
sudo apt-get install libasound2-dev
- 安装 FFmpeg:
sudo apt-get install ffmpeg
使用方法
相机
import 'package:switch_camera/switch_camera.dart';
void main() {
final camera = Camera();
// 列出最多10个设备
final devices = camera.getDevices(10);
print('可用设备: $devices');
// 打开摄像头设备
camera.open(0);
// 捕获帧
final frame = camera.captureFrame();
print('捕获帧: ${frame.length} 字节');
// 捕获翻转帧
final flippedFrame = camera.captureFrameFlip();
print('捕获翻转帧: ${flippedFrame.length} 字节');
// 流式传输帧
camera.streamFrames();
// 流式传输翻转帧
camera.streamFramesFlip();
// 开始视频写入
camera.startVideoWriter('output.mp4', 30.0, 1920, 1080);
// 写入帧
camera.writeFrame();
// 写入翻转帧
camera.writeFrameFlip();
// 释放摄像头
camera.release();
// 释放摄像头资源
camera.dispose();
}
音频录制器
import 'package:switch_camera/switch_camera.dart';
void main() {
final recorder = RustAudioRecorder();
// 开始录音
recorder.startRecording();
// 暂停录音
recorder.pauseRecording();
// 恢复录音
recorder.resumeRecording();
// 停止录音
recorder.stopRecording();
}
合并音频和视频
import 'package:switch_camera/switch_camera.dart';
void main() {
final result = mergeCamAudioVideo('output_with_audio.mp4');
print('合并结果: $result');
}
注意:为分发准备Linux应用
要将Flutter应用程序作为发布版本构建,请运行以下命令:
flutter build linux --release
之后,进入 build/linux/release/bundle/
目录并使用以下命令运行应用程序:
./projectname
通过运行应用程序在目录中,会自动将文件复制到 lib
文件夹下的 src/rust_native/librust_camera.so
。此文件负责使库在您的应用程序中正常工作。
API 参考
相机
-
List<int> getDevices(int limit)
列出指定限制内的可用摄像头设备。 -
void open(int index)
通过索引打开摄像头设备。 -
void release()
释放当前打开的摄像头设备。 -
Uint8List captureFrame()
捕获单个视频帧。 -
Uint8List captureFrameFlip()
捕获单个翻转的视频帧。 -
Stream<Uint8List> streamFrames()
流式传输视频帧。 -
Stream<Uint8List> streamFramesFlip()
流式传输翻转的视频帧。 -
void startVideoWriter(String filename, double fps, int width, int height)
开始向指定文件写入视频。 -
void startAVideoWriter(double fps, int width, int height)
不指定文件名开始视频写入。 -
void writeFrame()
写入视频帧。 -
void writeFrameFlip()
写入翻转的视频帧。 -
void dispose()
释放摄像头资源。
RustAudioRecorder
-
void startRecording()
开始音频录制。 -
void stopRecording()
停止音频录制。 -
void pauseRecording()
暂停音频录制。 -
void resumeRecording()
恢复音频录制。
合并函数
String mergeCamAudioVideo(String outputFilePath)
将录制的摄像头视频和音频合并到指定输出文件。
作者
Zacchaeus Oluwole
- LinkedIn: https://www.linkedin.com/in/zacchaeus-oluwole/
- X: https://x.com/ZTechPlus
- Email: zacchaeusoluwole@gmail.com
- Github: https://github.com/Zacchaeus-Oluwole
示例代码
以下是 switch_camera
插件的一个完整示例Demo:
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:switch_camera/switch_camera.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Switch Camera Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Switch Camera Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late Stream<Uint8List> cam;
final camera = Camera();
[@override](/user/override)
void initState() {
super.initState();
camera.open(0);
cam = camera.streamFrames();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("计算机视觉"),
StreamBuilder<Uint8List>(
stream: cam,
builder: (context, snap) {
final data = snap.data;
if (data != null)
return Image.memory(
data,
gaplessPlayback: true,
);
return const CircularProgressIndicator();
},
)
],
),
),
);
}
}
更多关于Flutter摄像头切换插件switch_camera的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter摄像头切换插件switch_camera的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter应用中使用switch_camera
插件来切换摄像头的示例代码。这个插件允许你在运行时从后置摄像头切换到前置摄像头,或者反过来。
首先,你需要在你的pubspec.yaml
文件中添加switch_camera
依赖:
dependencies:
flutter:
sdk: flutter
switch_camera: ^0.4.0 # 请检查最新版本号并替换
然后运行flutter pub get
来安装依赖。
接下来,在你的Flutter项目中,你可以按照以下步骤使用switch_camera
插件:
- 导入必要的包:
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:switch_camera/switch_camera.dart';
注意:camera
插件是switch_camera
依赖的一部分,所以你也需要确保camera
插件也被正确安装和配置。
- 请求相机权限(在Android和iOS上都需要):
在AndroidManifest.xml
中添加:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
在Info.plist
中添加:
<key>NSCameraUsageDescription</key>
<string>Need camera access</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Need photo library access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access</string>
- 创建主应用组件:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CameraApp(),
);
}
}
- 创建CameraApp组件:
class CameraApp extends StatefulWidget {
@override
_CameraAppState createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
CameraController? controller;
List<CameraDescription>? cameras;
CameraLensDirection currentLensDirection = CameraLensDirection.back;
Future<void> _initializeCamera() async {
cameras = await availableCameras();
if (cameras!.isNotEmpty) {
controller = new CameraController(
cameras![currentLensDirection == CameraLensDirection.back ? 0 : 1],
ResolutionPreset.high,
enableAudio: true,
);
controller!.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
Future<void> _switchCamera() async {
if (controller != null) {
await controller!.dispose();
}
currentLensDirection =
currentLensDirection == CameraLensDirection.back
? CameraLensDirection.front
: CameraLensDirection.back;
if (cameras!.isNotEmpty) {
controller = new CameraController(
cameras![currentLensDirection == CameraLensDirection.back ? 0 : 1],
ResolutionPreset.high,
enableAudio: true,
);
controller!.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
@override
void initState() {
super.initState();
_initializeCamera();
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Camera App'),
),
body: cameras == null || !controller!.value.isInitialized
? Center(child: Text('Loading...'))
: Stack(
children: <Widget>[
CameraPreview(controller!),
Align(
alignment: Alignment.bottomCenter,
child: Container(
child: ElevatedButton(
onPressed: _switchCamera,
child: Text('Switch Camera'),
),
),
),
],
),
);
}
}
这个示例代码展示了如何初始化相机、显示相机预览、并在点击按钮时切换摄像头。注意,CameraController
的初始化应该在UI线程上异步进行,并在dispose
方法中释放资源以避免内存泄漏。
确保你已经正确配置了camera
和switch_camera
插件的权限和依赖,这样你的应用才能成功访问和切换摄像头。