Flutter视频录制与回放插件flutter_kinescope_sdk的使用

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

Flutter视频录制与回放插件flutter_kinescope_sdk的使用

简介

flutter_kinescope_sdk 是一个用于Flutter应用的Kinescope播放器插件,支持Android和iOS平台。该插件底层依赖于 flutter_inappwebview 实现。

许可证

Apache License, Version 2.0

系统要求

  • Android: 需要 minSdkVersion 17 并且需要添加对 androidx 的支持(参见 AndroidX Migration
  • iOS: 需要 --ios-language swift 和 Xcode版本 >= 11

安装

在你的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  flutter_kinescope_sdk: ^0.1.10

使用方法

下面是一个简单的示例,展示了如何在Flutter应用中集成和使用 flutter_kinescope_sdk 插件。

示例代码

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

const _initialVideoId = 'sEsxJQ7Hi4QLWwbmZEFfgz';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Kinescope SDK example',
      theme: ThemeData(
        primarySwatch: Colors.purple,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final _textEditingController = TextEditingController(text: _initialVideoId);
  late KinescopePlayerController _kinescopeController;

  @override
  void initState() {
    super.initState();
    _kinescopeController = KinescopePlayerController(
      _initialVideoId,
      parameters: const PlayerParameters(
        watermark: WatermarkParameters(
          mode: 'random',
          text: 'water-text',
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<KinescopePlayerStatus>(
      stream: _kinescopeController.status,
      initialData: KinescopePlayerStatus.unknown,
      builder: (context, snapshot) {
        final isUnknown = snapshot.data == KinescopePlayerStatus.unknown;

        return Scaffold(
          appBar: AppBar(
            title: const Text('Kinescope SDK example'),
          ),
          body: Column(
            children: [
              SizedBox(
                height: MediaQuery.of(context).size.height / 4,
                child: KinescopePlayer(
                  controller: _kinescopeController,
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: TextField(
                  controller: _textEditingController,
                  decoration: const InputDecoration(labelText: 'Video ID'),
                  onSubmitted: (id) {
                    _kinescopeController.load(id);
                  },
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    IconButton(
                      onPressed: !isUnknown ? _play : null,
                      icon: const Icon(Icons.play_arrow),
                    ),
                    IconButton(
                      onPressed: !isUnknown ? _pause : null,
                      icon: const Icon(Icons.pause),
                    ),
                    IconButton(
                      onPressed: !isUnknown ? _stop : null,
                      icon: const Icon(Icons.stop),
                    ),
                    IconButton(
                      onPressed: !isUnknown ? _unmute : null,
                      icon: const Icon(Icons.volume_up),
                    ),
                    IconButton(
                      onPressed: !isUnknown ? _mute : null,
                      icon: const Icon(Icons.volume_off),
                    ),
                  ],
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Column(
                      children: [
                        IconButton(
                          onPressed: !isUnknown ? _rewindBackward : null,
                          icon: const Icon(Icons.fast_rewind),
                          tooltip: 'rewind 10 seconds backward',
                        ),
                        const Text('- 10 sec'),
                      ],
                    ),
                    TextButton(
                      onPressed: !isUnknown ? _seekToCenter : null,
                      child: const Text('seek to center'),
                    ),
                    Column(
                      children: [
                        IconButton(
                          onPressed: !isUnknown ? _rewindForward : null,
                          icon: const RotatedBox(
                            quarterTurns: 2,
                            child: Icon(Icons.fast_rewind),
                          ),
                          tooltip: 'rewind 10 seconds forward',
                        ),
                        const Text('+ 10 sec'),
                      ],
                    ),
                  ],
                ),
              ),
              Container(
                width: double.infinity,
                height: 50,
                margin: const EdgeInsets.all(8.0),
                decoration: BoxDecoration(
                  color: Theme.of(context).primaryColor,
                  borderRadius: BorderRadius.circular(16),
                ),
                child: Center(
                  child: Text(
                    'KinescopePlayerStatus: ${snapshot.data}',
                    style: const TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  void _pause() {
    _kinescopeController.pause();
  }

  void _play() {
    _kinescopeController.play();
  }

  void _stop() {
    _kinescopeController.stop();
  }

  void _unmute() {
    _kinescopeController.unmute();
  }

  void _mute() {
    _kinescopeController.mute();
  }

  Future<void> _rewindBackward() async {
    final currentTime = await _kinescopeController.getCurrentTime();

    final duration = Duration(
      seconds: currentTime.inSeconds - 10 > 0 ? currentTime.inSeconds - 10 : 0,
    );

    _kinescopeController.seekTo(duration);
  }

  Future<void> _rewindForward() async {
    final currentTime = await _kinescopeController.getCurrentTime();

    _kinescopeController.seekTo(
      currentTime + const Duration(seconds: 10),
    );
  }

  Future<void> _seekToCenter() async {
    final duration = await _kinescopeController.getDuration();
    _kinescopeController.seekTo(
      Duration(
        seconds: duration.inSeconds ~/ 2,
      ),
    );
  }
}

可用方法

以下是 KinescopePlayerController 提供的方法列表:

方法 描述
play() 播放当前加载的视频
pause() 暂停当前播放的视频
stop() 停止并取消当前视频的加载
load(String videoId) 加载并播放指定的视频
getCurrentTime() 返回当前播放位置
getDuration() 返回视频的总时长
seekTo(Duration position) 跳转到视频中的指定时间点
mute() 静音
unmute() 取消静音
setVolume(double volume) 设置音量(仅适用于Android)

PlayerParameters 参数

你可以通过 PlayerParameters 来设置初始的Kinescope播放器参数:

参数 描述
autoplay 是否自动播放视频,默认为 false
muted 是否静音,默认为 true
loop 视频结束后是否自动重新开始播放
userAgent 覆盖默认的UserAgent
externalId 代表外部系统的用户ID,用于分析,默认为空字符串
autofocus 设置焦点到播放器,默认为 true
playsinline 在不全屏的情况下播放视频
preload 预加载视频元数据,默认为 true
texttrack 启用字幕
dnt 禁用发送分析数据
background 禁用任何控件,并将 autoplay, muted, loop 设置为 true
t 指定跳转的时间点
transparent 透明背景颜色
speedbtn 显示播放速率按钮
header 显示头部
controls 显示控制按钮
disableFiles 隐藏附加材料
watermark 设置水印

更多详细信息可以参考 GitHub上的示例


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

1 回复

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


当然,以下是如何在Flutter项目中使用flutter_kinescope_sdk插件进行视频录制与回放的示例代码。请注意,这个示例假设你已经在pubspec.yaml文件中添加了flutter_kinescope_sdk依赖,并运行了flutter pub get

首先,确保你的pubspec.yaml文件包含以下依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_kinescope_sdk: ^latest_version # 替换为实际的最新版本号

接下来,创建一个Flutter项目并添加以下代码。

1. 初始化插件和权限

android/app/src/main/AndroidManifest.xml中,添加必要的权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

ios/Runner/Info.plist中,添加相机和麦克风权限请求(如果需要iOS支持):

<key>NSCameraUsageDescription</key>
<string>App needs access to the camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>App needs access to the microphone</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>App needs access to the photo library</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App needs access to the photo library</string>

2. 主代码实现

在你的main.dart文件中,实现视频录制与回放功能:

import 'package:flutter/material.dart';
import 'package:flutter_kinescope_sdk/flutter_kinescope_sdk.dart';
import 'package:permission_handler/permission_handler.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  FlutterKinescope? _kinescope;
  String? _videoPath;

  @override
  void initState() {
    super.initState();
    _initKinescope();
  }

  Future<void> _initKinescope() async {
    // 请求必要的权限
    var status = await Permission.camera.status;
    if (!status.isGranted) {
      await Permission.camera.request();
    }
    status = await Permission.microphone.status;
    if (!status.isGranted) {
      await Permission.microphone.request();
    }
    status = await Permission.storage.status;
    if (!status.isGranted) {
      await Permission.storage.request();
    }

    // 初始化Kinescope
    _kinescope = FlutterKinescope();
  }

  Future<void> _startRecording() async {
    if (_kinescope!.isRecording) {
      return;
    }
    String? resultPath = await _kinescope!.startRecord({
      'videoQuality': 'HIGH', // 可以选择 'LOW', 'MEDIUM', 'HIGH'
      'outputPath': '/storage/emulated/0/DCIM/Camera/', // 指定输出路径,可以是绝对路径或相对路径
    });
    setState(() {
      _videoPath = resultPath;
    });
  }

  Future<void> _stopRecording() async {
    if (!_kinescope!.isRecording) {
      return;
    }
    await _kinescope!.stopRecord();
  }

  Future<void> _playVideo() async {
    if (_videoPath == null) {
      return;
    }
    // 使用系统的视频播放器打开录制的视频
    await _kinescope!.playVideo(_videoPath!);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Kinescope SDK Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _startRecording,
              child: Text('Start Recording'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _stopRecording,
              child: Text('Stop Recording'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _playVideo,
              child: Text('Play Video'),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _kinescope?.dispose();
    super.dispose();
  }
}

3. 注意事项

  • 确保你已经添加了permission_handler依赖来处理权限请求。
  • 录制视频时,指定的输出路径需要确保应用有写权限。
  • 播放视频时,_kinescope!.playVideo方法会使用系统默认的视频播放器打开指定路径的视频文件。

这个示例代码展示了如何使用flutter_kinescope_sdk插件进行视频录制与回放。实际应用中,你可能需要根据具体需求进行更多的配置和处理。

回到顶部