Flutter视频录制插件widget_record_video的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter视频录制插件widget_record_video的使用

简介

widget_record_video 是一个Flutter插件,用于将屏幕上特定的小部件内容录制为视频。该插件使用 flutter_quick_video_encoder 从捕获的小部件帧中编码视频,从而在Flutter应用程序中实现高质量的视频录制。

此插件使用ffmpeg处理部分流程,因此构建APK时,应用程序容量会较大,但上传到应用商店时不会有问题。

DEMO

功能特性

  • 自定义屏幕录制:捕获应用程序中任何小部件的内容。
  • 录制时间限制:设置最大录制时长以控制视频长度。
  • 录制控制:随时开始和停止录制。
  • 完成回调:录制完成后获取视频文件路径。

安装

在您的 pubspec.yaml 文件中添加 widget_record_video

dependencies:
  widget_record_video: ^0.0.4

使用方法

录制小部件的初始设置

RecordingWidget 是用于录制指定小部件屏幕内容的主要小部件。以下是其设置方法:

final RecordingController _recordingController = RecordingController();

RecordingWidget(
  controller: _recordingController,
  limitTime: 120, // 最大录制时间为120秒
  onComplete: (filePath) {
    print("Video saved at: $filePath");
  },
  child: Container(
    color: Colors.blue,
    width: 200,
    height: 200,
    child: Center(child: Text("Recording Area")),
  ),
);

关键组件

RecordingWidget

此小部件封装了您要录制的内容。

  • child:要录制的小部件。
  • outputPath:自定义保存位置(可选)。
  • controller:管理录制动作的 RecordingController 实例。
  • limitTime:设置最大录制时间(秒)。对于无限录制,设置为 -1
  • onComplete:录制结束后的回调,提供保存视频的文件路径。

RecordingController

控制器允许您通过以下函数启动和停止录制:

  • start:启动录制。
  • stop:终止录制。
  • pauseRecord:暂停录制过程。
  • continueRecord:继续录制过程。

示例代码

下面是一个完整的示例代码,展示了如何在Flutter应用程序中使用 widget_record_video 插件:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'package:widget_record_video/widget_record_video.dart';
import 'package:video_player/video_player.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  final RecordingController recordingController = RecordingController();
  late AnimationController _animationController;
  late Animation<Color?> _colorAnimation;
  Timer? _colorChangeTimer;
  Timer? _timer; // 倒计时定时器
  VideoPlayerController? _videoController;
  String? _videoPath;
  int elapsedTime = 0; // 时间计数器变量

  String? outputPath;

  @override
  void initState() {
    super.initState();
    _getOutPutPath();
    // 启动颜色变化定时器
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 3), // 设置颜色变化周期的持续时间
    )..repeat(); // 无限重复动画

    // 创建颜色动画
    _colorAnimation = ColorTween(
      begin: Colors.blue, // 起始颜色
      end: Colors.red, // 结束颜色
    ).animate(_animationController);
  }

  @override
  void dispose() {
    _colorChangeTimer?.cancel();
    _timer?.cancel(); // 取消倒计时定时器
    _videoController?.dispose();
    super.dispose();
  }

  Future<void> _getOutPutPath() async {
    Directory? appDir = await getDownloadsDirectory();

    outputPath = '${appDir?.path}/result.mp4';
    setState(() {});
  }

  void _startRecording() {
    setState(() {
      elapsedTime = 0; // 重置时间计数器
    });
    recordingController.start?.call();

    // 启动倒计时定时器
    _timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
      setState(() {
        elapsedTime++;
      });
    });
  }

  Future<void> _stopRecording() async {
    recordingController.stop?.call();
    _timer?.cancel(); // 停止倒计时定时器
  }

  void _pauseRecording() async {
    recordingController.pauseRecord?.call();
  }

  void _continueRecording() {
    recordingController.continueRecord?.call();
  }

  Future<void> _onRecordingComplete(String path) async {
    setState(() {
      _videoPath = path;
    });

    _videoController = VideoPlayerController.file(File(path))
      ..initialize().then((_) {
        setState(() {});
        _videoController!.play();
      });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Widget Record Example App'),
        ),
        body: Center(
          child: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                SizedBox(
                  height: 300.0,
                  child: RecordingWidget(
                    controller: recordingController,
                    onComplete: _onRecordingComplete,
                    child: AnimatedBuilder(
                      animation: _colorAnimation,
                      builder: (context, child) {
                        return Container(
                          width: 200,
                          height: 200,
                          color: _colorAnimation.value,
                          child: Center(
                            child: Text(
                              '$elapsedTime', // 显示已过秒数
                              style: const TextStyle(
                                fontSize: 24,
                                color: Colors.white,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ),
                        );
                      },
                    ),
                  ),
                ),
                const SizedBox(height: 20),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    ElevatedButton(
                      onPressed: _startRecording,
                      child: const Text('Start Recording'),
                    ),
                    const SizedBox(width: 10),
                    ElevatedButton(
                      onPressed: _stopRecording,
                      child: const Text('Stop Recording'),
                    ),
                  ],
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    ElevatedButton(
                      onPressed: _pauseRecording,
                      child: const Text('Pause Recording'),
                    ),
                    const SizedBox(width: 10),
                    ElevatedButton(
                      onPressed: _continueRecording,
                      child: const Text('Continue Recording'),
                    ),
                  ],
                ),
                const SizedBox(height: 20),
                if (_videoPath != null) ...[
                  const Text('Playback of Recorded Video:'),
                  const SizedBox(height: 10),
                  _videoController != null && _videoController!.value.isInitialized
                      ? AspectRatio(
                          aspectRatio: _videoController!.value.aspectRatio,
                          child: VideoPlayer(_videoController!),
                        )
                      : const CircularProgressIndicator(),
                ],
              ],
            ),
          ),
        ),
      ),
    );
  }
}

注意事项

  • 此插件依赖于 flutter_quick_video_encoder 进行编码,请确保您的应用程序有适当的文件存储权限。
  • 为了获得最佳性能,请确保被录制的小部件具有固定大小,因为调整大小可能会导致录制问题。

贡献

我们欢迎贡献!如果您发现错误或有功能请求,请提交Issue。我们也欢迎您提交Pull Request。

许可证

本项目采用MIT许可证。详情请参阅LICENSE文件。


这个README提供了关于如何使用 widget_record_video 的清晰且详细的信息,使您可以轻松地将其集成到任何Flutter应用程序中并开始录制内容。


更多关于Flutter视频录制插件widget_record_video的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter视频录制插件widget_record_video的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 widget_record_video 插件在 Flutter 中进行视频录制的示例代码。这个插件允许你在 Flutter 应用中方便地集成视频录制功能。

首先,确保你已经在 pubspec.yaml 文件中添加了 widget_record_video 依赖:

dependencies:
  flutter:
    sdk: flutter
  widget_record_video: ^x.y.z  # 请替换为最新版本号

然后,运行 flutter pub get 来安装依赖。

接下来是一个完整的示例,展示如何使用 widget_record_video 插件:

import 'package:flutter/material.dart';
import 'package:widget_record_video/widget_record_video.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Video Recorder',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: VideoRecorderScreen(),
    );
  }
}

class VideoRecorderScreen extends StatefulWidget {
  @override
  _VideoRecorderScreenState createState() => _VideoRecorderScreenState();
}

class _VideoRecorderScreenState extends State<VideoRecorderScreen> {
  late RecordController recordController;
  String? recordedVideoPath;

  @override
  void initState() {
    super.initState();
    recordController = RecordController(
      // 设置视频录制配置,可以根据需要调整
      videoQuality: VideoQuality.high,
      isFrontCamera: false,
      isAutoFocus: true,
      isFlashOn: false,
      outputPath: "/storage/emulated/0/DCIM/Camera/recorded_video.mp4", // 请确保路径有写权限
    );

    // 监听录制状态变化
    recordController.addListener(() {
      if (recordController.isRecording) {
        print("Recording...");
      } else if (recordController.isStopped) {
        setState(() {
          recordedVideoPath = recordController.outputPath;
        });
        print("Recording stopped. Video saved at: $recordedVideoPath");
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Video Recorder"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            AspectRatio(
              aspectRatio: 16 / 9,
              child: RecordVideoWidget(controller: recordController),
            ),
            SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                ElevatedButton(
                  onPressed: () {
                    if (!recordController.isRecording) {
                      recordController.startRecording();
                    }
                  },
                  child: Text("Start Recording"),
                ),
                SizedBox(width: 20),
                ElevatedButton(
                  onPressed: () {
                    if (recordController.isRecording) {
                      recordController.stopRecording();
                    }
                  },
                  child: Text("Stop Recording"),
                ),
              ],
            ),
            if (recordedVideoPath != null) {
              SizedBox(height: 20),
              Text("Recorded Video Path: $recordedVideoPath"),
            },
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    recordController.dispose();
    super.dispose();
  }
}

代码说明:

  1. 依赖导入:确保在 pubspec.yaml 中添加 widget_record_video 依赖。
  2. 初始化 RecordController:在 initState 方法中初始化 RecordController,并设置视频录制的相关配置,如视频质量、摄像头方向、自动对焦等。
  3. 监听录制状态:通过 recordController.addListener 监听录制状态变化,在录制开始和停止时执行相应操作。
  4. UI 布局:使用 RecordVideoWidget 显示视频预览,并提供开始和停止录制的按钮。
  5. 保存录制视频路径:在录制停止时,将视频路径保存到 recordedVideoPath 变量中,并在 UI 上显示。
  6. 资源释放:在 dispose 方法中释放 RecordController,以避免内存泄漏。

请确保你的应用具有写入存储的权限,特别是在 Android 上,你需要在 AndroidManifest.xml 中声明 WRITE_EXTERNAL_STORAGE 权限,并在运行时请求权限。

这个示例提供了一个基本的视频录制功能,你可以根据需要进行扩展和自定义。

回到顶部