Flutter 实现视频播放

1,086 阅读1分钟

使用pub上现成的三方库实现视频播放能力,如下两种方案,硬解码方案,如播放器宽高比例与视频内容宽高比例不一致时,会出现图像压缩变形的问题,我们最终选择第二种方案。

  • video_player: ^1.0.1 硬解码
  • fijkplayer: ^0.8.7 软解码

闲话不多说,直接进入代码环节

dependencies:
    fijkplayer: ^0.8.7

封装videoPlayer,copy直接可用:

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

// ignore: must_be_immutable
class VideoWidget extends StatefulWidget {
  final String _playUrl;
  final bool _loop;
  int _startSeconds = 0; //播放起始时间

  VideoWidget(
    this._playUrl,
    this._loop, {
    int startSeconds,
  }) {
    _startSeconds = startSeconds;
  }

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

class _VideoWidgetState extends State<VideoWidget> {
  final FijkPlayer _player = FijkPlayer();
  bool _hold = true;

  @override
  void initState() {
    super.initState();
    //视频路径
    _player.setDataSource(widget._playUrl, showCover: true);
    ////0表示使用av解码器,1表示使用媒体解码器
    //_player.setOption(FijkOption.playerCategory, "mediacodec", 1);

    //循环播放
    if (widget._loop) {
      _player.setLoop(0);
    }

    _player.prepareAsync();
  }

  @override
  void dispose() {
    _player.release();
    _player.removeListener(_ijkValueListener);
    super.dispose();
  }

  ///用于监听播放器状态
  void _ijkValueListener() async {
    if (_player.state == FijkState.prepared) {
      final int initSeconds = widget._startSeconds;
      if (initSeconds > 0) {
        _player.seekTo(initSeconds);
      }
      if (_hold) {
        setState(() {
          _hold = false;
        });
      }
      _player.start();
    }
  }

  @override
  Widget build(BuildContext context) {
    return _hold
        ? PlayerHolder()
        : FijkView(
            fit: FijkFit.fitWidth,
            color: Colors.black,
            player: _player,
          );
  }
}

//视频缓冲过程中显示这个页面,可以加个loading效果
class PlayerHolder extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black,
    );
  }
}