📜  Flutter – 处理视频(1)

📅  最后修改于: 2023-12-03 15:00:48.433000             🧑  作者: Mango

Flutter - 处理视频

随着视频应用的普及,我们需要在我们的Flutter应用中处理视频。Flutter提供了一些库来处理视频,包括播放视频,录制视频,剪辑视频等。

播放视频

我们可以使用video_player库在Flutter中播放视频。先在pubspec.yaml文件中添加以下依赖:

dependencies:
  video_player: ^2.1.6

然后在需要使用VideoPlayer的地方导入video_player库:

import 'package:video_player/video_player.dart';

使用VideoPlayer非常简单,只需要传递视频的URL即可:

VideoPlayerController _controller;

@override
void initState() {
  super.initState();
  _controller = VideoPlayerController.network(
      'https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4')
    ..initialize().then((_) {
      // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
      setState(() {});
    });
}

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

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Video Player'),
    ),
    body: Center(
      child: _controller.value.isInitialized
          ? AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: VideoPlayer(_controller),
            )
          : Container(),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {
        setState(() {
          _controller.value.isPlaying
              ? _controller.pause()
              : _controller.play();
        });
      },
      child: Icon(
        _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
      ),
    ),
  );
}

我们创建一个VideoPlayerController,然后使用VideoPlayerController.network方法传递视频的URL。然后我们初始化VideoPlayerController并使用initialize在播放器初始化后回调。然后我们使用VideoPlayer窗口小部件播放视频。

录制视频

如果我们想要在Flutter应用中录制视频,我们可以使用camera库。首先在pubspec.yaml文件中添加以下依赖:

dependencies:
  camera: ^0.9.4+5

然后在需要使用CameraController的地方导入camera库:

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

class RecordVideo extends StatefulWidget {
  @override
  _RecordVideoState createState() => _RecordVideoState();
}

class _RecordVideoState extends State<RecordVideo> {
  CameraController _controller;
  Future<void> _initializeControllerFuture;

  @override
  void initState() {
    super.initState();
    _controller = CameraController(
      cameras[0],
      ResolutionPreset.medium,
    );
    _initializeControllerFuture = _controller.initialize();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Record Video'),
      ),
      body: FutureBuilder<void>(
        future: _initializeControllerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return CameraPreview(_controller);
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.camera_alt),
        onPressed: () async {
          try {
            await _initializeControllerFuture;

            final Directory extDir = await getApplicationDocumentsDirectory();
            final String dirPath = '${extDir.path}/Movies/flutter_test';
            await Directory(dirPath).create(recursive: true);
            final String filePath = '$dirPath/${DateTime.now()}.mp4';

            await _controller.startVideoRecording(filePath);
            await Future.delayed(Duration(seconds: 10));
            await _controller.stopVideoRecording();

            final videoPlayerController = VideoPlayerController.file(File(filePath));
            await videoPlayerController.initialize();
            Navigator.push(context, MaterialPageRoute(builder: (context) => PlayVideo(videoPlayerController: videoPlayerController)));
          } catch (e) {
            print(e);
          }
        },
      ),
    );
  }
}

我们创建了一个CameraController并带有所需的分辨率参数。然后我们使用initialize初始化控制器。然后使用CameraPreview小部件在UI中显示预览。最后,我们使用startVideoRecording方法开始录制视频,使用stopVideoRecording方法停止录制视频。我们使用VideoPlayerController.file方法加载录制的文件并在屏幕上播放。

剪辑视频

如果我们想要在Flutter应用中剪辑视频,我们可以使用video_editor库。请注意,这个库目前仍然是实验性的API,并且可以随时发生变化。

首先,在pubspec.yaml文件中添加以下依赖:

dependencies:
  video_editor: ^0.0.1-experimental

然后在需要使用VideoEditor的地方导入video_editor库:

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

class EditVideo extends StatefulWidget {
  final File videoFile;

  EditVideo({Key key, this.videoFile}) : super(key: key);

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

class _EditVideoState extends State<EditVideo> {
  String _outputPath;
  VideoPlayerController _outputController;
  final _editor = VideoEditor();

  Future<void> _processVideo() async {
    try {
      setState(() {
        _outputPath = null;
        _outputController?.dispose();
        _outputController = null;
      });

      final info = await _editor.getMediaInformation(widget.videoFile.path);

      final filter = TrimFilter(
        startTime: Duration(seconds: 5),
        endTime: Duration(seconds: 10),
        keepAudio: true,
      );

      final output = await _editor.encodeVideo(
        widget.videoFile.path,
        _createTempPath(),
        VideoFormat.h264,
        filter: filter,
      );

      setState(() {
        _outputPath = output;
        _outputController = VideoPlayerController.file(File(_outputPath))
          ..initialize().then((_) {
            setState(() {});
          });
      });
    } catch (e, st) {
      print('$e\n$st');
    }
  }

  String _createTempPath() {
    final directory = Directory.systemTemp;
    final filename = 'flutter_test_${DateTime.now().millisecondsSinceEpoch}.mp4';
    return '${directory.path}/$filename';
  }

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

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

  Widget _buildPlayer() {
    return Center(
      child: _outputController.value.isInitialized
          ? AspectRatio(
              aspectRatio: _outputController.value.aspectRatio,
              child: VideoPlayer(_outputController),
            )
          : CircularProgressIndicator(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Edit Video'),
      ),
      body: _outputPath == null
          ? Center(child: CircularProgressIndicator())
          : Column(
              children: [
                Expanded(child: _buildPlayer()),
              ],
            ),
    );
  }
}

我们创建一个VideoEditor实例并加载要剪辑的视频文件。然后,我们指定所需的起始时间和持续时间,并使用TrimFilter创建一个Filter。使用encodeVideo方法,我们将所需的输出格式、Filter和文件路径传递给VideoEditor库,以便它使用新的参数进行编码。

结论

现在您已经了解了如何在Flutter应用中处理视频。这样的功能将使您的应用更加多样化和有趣,并使用户根据需要进行更多操作。

Markdown Code:

# Flutter - 处理视频

随着视频应用的普及,我们需要在我们的Flutter应用中处理视频。Flutter提供了一些库来处理视频,包括播放视频,录制视频,剪辑视频等。

## 播放视频

我们可以使用`video_player`库在Flutter中播放视频。先在`pubspec.yaml`文件中添加以下依赖:

```yaml
dependencies:
  video_player: ^2.1.6

然后在需要使用VideoPlayer的地方导入video_player库:

import 'package:video_player/video_player.dart';

使用VideoPlayer非常简单,只需要传递视频的URL即可:

VideoPlayerController _controller;

@override
void initState() {
  super.initState();
  _controller = VideoPlayerController.network(
      'https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4')
    ..initialize().then((_) {
      // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
      setState(() {});
    });
}

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

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Video Player'),
    ),
    body: Center(
      child: _controller.value.isInitialized
          ? AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: VideoPlayer(_controller),
            )
          : Container(),
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {
        setState(() {
          _controller.value.isPlaying
              ? _controller.pause()
              : _controller.play();
        });
      },
      child: Icon(
        _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
      ),
    ),
  );
}

我们创建一个VideoPlayerController,然后使用VideoPlayerController.network方法传递视频的URL。然后我们初始化VideoPlayerController并使用initialize在播放器初始化后回调。然后我们使用VideoPlayer窗口小部件播放视频。

录制视频

如果我们想要在Flutter应用中录制视频,我们可以使用camera库。首先在pubspec.yaml文件中添加以下依赖:

dependencies:
  camera: ^0.9.4+5

然后在需要使用CameraController的地方导入camera库:

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

class RecordVideo extends StatefulWidget {
  @override
  _RecordVideoState createState() => _RecordVideoState();
}

class _RecordVideoState extends State<RecordVideo> {
  CameraController _controller;
  Future<void> _initializeControllerFuture;

  @override
  void initState() {
    super.initState();
    _controller = CameraController(
      cameras[0],
      ResolutionPreset.medium,
    );
    _initializeControllerFuture = _controller.initialize();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Record Video'),
      ),
      body: FutureBuilder<void>(
        future: _initializeControllerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return CameraPreview(_controller);
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.camera_alt),
        onPressed: () async {
          try {
            await _initializeControllerFuture;

            final Directory extDir = await getApplicationDocumentsDirectory();
            final String dirPath = '${extDir.path}/Movies/flutter_test';
            await Directory(dirPath).create(recursive: true);
            final String filePath = '$dirPath/${DateTime.now()}.mp4';

            await _controller.startVideoRecording(filePath);
            await Future.delayed(Duration(seconds: 10));
            await _controller.stopVideoRecording();

            final videoPlayerController = VideoPlayerController.file(File(filePath));
            await videoPlayerController.initialize();
            Navigator.push(context, MaterialPageRoute(builder: (context) => PlayVideo(videoPlayerController: videoPlayerController)));
          } catch (e) {
            print(e);
          }
        },
      ),
    );
  }
}

我们创建了一个CameraController并带有所需的分辨率参数。然后我们使用initialize初始化控制器。然后使用CameraPreview小部件在UI中显示预览。最后,我们使用startVideoRecording方法开始录制视频,使用stopVideoRecording方法停止录制视频。我们使用VideoPlayerController.file方法加载录制的文件并在屏幕上播放。

剪辑视频

如果我们想要在Flutter应用中剪辑视频,我们可以使用video_editor库。请注意,这个库目前仍然是实验性的API,并且可以随时发生变化。

首先,在pubspec.yaml文件中添加以下依赖:

dependencies:
  video_editor: ^0.0.1-experimental

然后在需要使用VideoEditor的地方导入video_editor库:

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

class EditVideo extends StatefulWidget {
  final File videoFile;

  EditVideo({Key key, this.videoFile}) : super(key: key);

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

class _EditVideoState extends State<EditVideo> {
  String _outputPath;
  VideoPlayerController _outputController;
  final _editor = VideoEditor();

  Future<void> _processVideo() async {
    try {
      setState(() {
        _outputPath = null;
        _outputController?.dispose();
        _outputController = null;
      });

      final info = await _editor.getMediaInformation(widget.videoFile.path);

      final filter = TrimFilter(
        startTime: Duration(seconds: 5),
        endTime: Duration(seconds: 10),
        keepAudio: true,
      );

      final output = await _editor.encodeVideo(
        widget.videoFile.path,
        _createTempPath(),
        VideoFormat.h264,
        filter: filter,
      );

      setState(() {
        _outputPath = output;
        _outputController = VideoPlayerController.file(File(_outputPath))
          ..initialize().then((_) {
            setState(() {});
          });
      });
    } catch (e, st) {
      print('$e\n$st');
    }
  }

  String _createTempPath() {
    final directory = Directory.systemTemp;
    final filename = 'flutter_test_${DateTime.now().millisecondsSinceEpoch}.mp4';
    return '${directory.path}/$filename';
  }

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

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

  Widget _buildPlayer() {
    return Center(
      child: _outputController.value.isInitialized
          ? AspectRatio(
              aspectRatio: _outputController.value.aspectRatio,
              child: VideoPlayer(_outputController),
            )
          : CircularProgressIndicator(),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Edit Video'),
      ),
      body: _outputPath == null
          ? Center(child: CircularProgressIndicator())
          : Column(
              children: [
                Expanded(child: _buildPlayer()),
              ],
            ),
    );
  }
}

我们创建一个VideoEditor实例并加载要剪辑的视频文件。然后,我们指定所需的起始时间和持续时间,并使用TrimFilter创建一个Filter。使用encodeVideo方法,我们将所需的输出格式、Filter和文件路径传递给VideoEditor库,以便它使用新的参数进行编码。

结论

现在您已经了解了如何在Flutter应用中处理视频。这样的功能将使您的应用更加多样化和有趣,并使用户根据需要进行更多操作。