Flutter视频播放插件flutter_nimplayer的使用
Flutter视频播放插件flutter_nimplayer的使用
Flutter 版的网易云信点播播放器 SDK,支持 Android & iOS。
开始使用
添加依赖:
dependencies:
flutter_nimplayer: ^{latest_version}
用法
第一步,创建播放器
player = FlutterNimplayerFactory.createPlayer();
第二步,添加播放器视图
NimplayerView(
onCreated: (viewId) {
initAndPlay(viewId);
},
x: 0,
y: 0,
width: viewWidth,
height: viewHeight,
);
第三步,设置播放源并播放
void initAndPlay(int viewId) {
// 建立连接
player?.setPlayerView(viewId);
// 设置播放链接
player?.setUrl(url);
// 准备播放
player?.prepare();
}
具体示例请查看项目的 example
文件夹,更多播放器接口以及播放回调请查看项目源码。
完整示例代码
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_nimplayer/flutter_nimplayer.dart';
import 'package:flutter_nimplayer_example/ext/int.dart';
import 'package:flutter_nimplayer_example/widget/translucent_container.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
/// 播放 url
String url =
'http://jdvodma74obxu.vod.126.net/jdvodma74obxu/elyOEqRN_4973406720_sd.m3u8?'
'wsSecret=b316d80189ffc977e11dd1f79eaa645d&'
'wsTime=1667546938';
/// 是否以全屏方式播放
bool fullscreenMode = false;
/// region 播放相关
FlutterNimplayer? player;
int _videoViewId = -1;
bool videoPlaying = false;
bool videoLoading = false;
bool videoEnded = false;
// endregion
/// region 进度条相关
Timer? videoControlTimer;
bool videoControlVisible = false;
int _videoLength = 0;
String videoTotalTime = '00.00';
String videoPlayedTime = '00:00';
double videoPosition = 0.0;
bool _slidingInProgress = false;
// endregion
[@override](/user/override)
void initState() {
super.initState();
player = FlutterNimplayerFactory.createPlayer();
player?.setOnPrepared((playerId) async {
videoPlaying = true;
_showVideoControlBar();
var size = await player?.getVideoSize();
if (size != null && size is Map) {
var width = size['width'];
var height = size['height'];
print('flutter_nimplayer: 视频宽度 = $width, 高度 = $height');
}
_videoLength = await player?.getDuration();
setState(() {
videoTotalTime = _videoLength.millisecondsToTimeString();
});
player!.setOnLoadingStatusListener(loadingBegin: (playerId) {
setState(() {
videoLoading = true;
});
}, loadingProgress: (playerId, percent) {
// 播放进度回调仅支持安卓。取决于视频长度,有可能当加载进度大于 30 时就可以播放了
if (percent > 70) {
videoLoading = false;
}
}, loadingEnd: (playerId) {
videoLoading = false;
});
player!.setOnCompletion((playerId, code, extra) {
setState(() {
videoPosition = 1;
videoEnded = true;
videoPlaying = false;
videoControlVisible = false;
});
player!.setOnError((playerId, code, extra) {
print(
'flutter_nimplayer: playerId = $playerId, code = $code, extra = $extra');
});
});
});
// 使用定时器获取播放进度,安卓上支持小于一秒内的刷新,iOS 上只支持秒级刷新
Timer.periodic(const Duration(milliseconds: 200), (timer) async {
int pos = 0;
if (!_slidingInProgress && videoPlaying) {
pos = await player?.getCurrentPosition() ?? 0;
double newPosition = pos / _videoLength;
if (newPosition < 0) {
newPosition = 0;
} else if (newPosition > 1) {
newPosition = 1;
}
setState(() {
videoPosition = newPosition;
});
String newTime = pos.millisecondsToTimeString();
if (newTime != videoPlayedTime) {
setState(() {
videoPlayedTime = newTime;
});
}
}
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Builder(builder: (context) {
var width = MediaQuery.of(context).size.width;
var height = MediaQuery.of(context).size.height;
if (!fullscreenMode) {
height = width * 9 / 16;
}
// 如果是全屏则旋转屏幕并反向设置宽高
return SafeArea(
child: RotatedBox(
quarterTurns: fullscreenMode ? 1 : 0,
child: SizedBox(
width: fullscreenMode ? height : width,
height: fullscreenMode ? width : height,
child: Stack(
children: [
_buildPlayerView(width, height),
_buildGestureDetector(),
_buildLoadingIndicator(),
_buildControlBar(),
_buildReplayButton(),
],
),
),
),
);
}),
),
);
}
Widget _buildPlayerView(double width, double height) {
return NimplayerView(
onCreated: (viewId) {
initAndPlay(viewId);
},
x: 0,
y: 0,
width: fullscreenMode ? height : width,
height: fullscreenMode ? width : height,
);
}
Widget _buildGestureDetector() {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
toggleVideoControlBar();
},
);
}
Widget _buildLoadingIndicator() {
if (videoLoading) {
return Center(
child: TranslucentContainer(
padding: const EdgeInsets.all(8),
child: Theme(
data: ThemeData(
cupertinoOverrideTheme:
const CupertinoThemeData(brightness: Brightness.dark)),
child: const CupertinoActivityIndicator()),
),
);
}
return Container();
}
Widget _buildControlBar() {
if (videoControlVisible) {
return Positioned(
left: fullscreenMode ? 50 : 0,
right: fullscreenMode ? 50 : 0,
bottom: 0,
child: Container(
color: Colors.black38,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
onPressed: () {
toggleVideoPlayAndPause();
},
icon: Icon(videoPlaying ? Icons.pause : Icons.play_arrow,
color: Colors.white, size: 24)),
SizedBox(
width: 35,
child: Text(
videoPlayedTime,
style: const TextStyle(color: Colors.white, fontSize: 11),
),
),
SizedBox(
width: 40,
child: Text(
'/ $videoTotalTime',
style: TextStyle(color: Colors.grey[400], fontSize: 11),
),
),
Expanded(
child: SliderTheme(
data: const SliderThemeData(
trackHeight: 2,
thumbColor: Colors.white,
thumbShape: RoundSliderThumbShape(
enabledThumbRadius: 5,
pressedElevation: 2,
),
),
child: Slider(
value: videoPosition,
activeColor: Colors.blue,
inactiveColor: const Color(0xFF929BA2),
onChanged: (value) {
slideTo(value);
},
onChangeEnd: (double value) {
seekTo(value);
},
)),
),
],
),
),
);
}
return Container();
}
Widget _buildReplayButton() {
if (videoEnded) {
return Center(
child: GestureDetector(
onTap: () {
replayVideo();
},
child: TranslucentContainer(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const [
Icon(
Icons.replay,
color: Colors.white,
size: 30,
),
SizedBox(height: 4),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text('重播', style: TextStyle(color: Colors.white)),
),
],
),
),
),
);
}
return Container();
}
void initAndPlay(int viewId) {
_videoViewId = viewId;
player?.setPlayerView(viewId);
player?.setUrl(url);
// player?.setScalingMode(1);
player?.prepare();
}
void toggleVideoControlBar() {
if (videoEnded) return;
if (videoControlVisible) {
setState(() {
videoControlVisible = false;
});
} else {
_showVideoControlBar();
}
}
void _showVideoControlBar() {
setState(() {
videoControlVisible = true;
});
if (videoControlTimer != null && videoControlTimer!.isActive) {
videoControlTimer!.cancel();
}
videoControlTimer = Timer(const Duration(seconds: 5), () {
setState(() {
videoControlVisible = false;
});
});
}
void toggleVideoPlayAndPause() {
_showVideoControlBar();
if (videoPlaying) {
player!.pause();
} else {
player!.play();
}
setState(() {
videoPlaying = !videoPlaying;
});
}
void seekTo(double value) {
slideTo(value);
player!.seekTo((value * _videoLength).toInt(), true);
setState(() {
videoLoading = false;
_slidingInProgress = false;
});
}
void slideTo(double value) {
_showVideoControlBar();
setState(() {
videoPosition = value;
_slidingInProgress = true;
});
}
void replayVideo() {
setState(() {
videoPosition = 0;
videoPlayedTime = '00:00';
videoEnded = false;
});
toggleVideoPlayAndPause();
}
[@override](/user/override)
void dispose() {
player?.destroy();
videoControlTimer?.cancel();
super.dispose();
}
}
更多关于Flutter视频播放插件flutter_nimplayer的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter视频播放插件flutter_nimplayer的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_nimplayer
是一个用于在 Flutter 应用中播放视频的插件。它基于 NativePlayer
,支持 Android 和 iOS 平台。以下是如何在你的 Flutter 项目中使用 flutter_nimplayer
的步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 flutter_nimplayer
插件的依赖:
dependencies:
flutter:
sdk: flutter
flutter_nimplayer: ^0.0.1 # 请检查最新版本
然后运行 flutter pub get
来获取依赖。
2. 在代码中使用 flutter_nimplayer
在你的 Flutter 代码中导入 flutter_nimplayer
,并使用它来播放视频。
import 'package:flutter/material.dart';
import 'package:flutter_nimplayer/flutter_nimplayer.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: VideoPlayerScreen(),
);
}
}
class VideoPlayerScreen extends StatefulWidget {
@override
_VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
late NativePlayerController _controller;
@override
void initState() {
super.initState();
_controller = NativePlayerController();
_controller.initialize().then((_) {
// 初始化完成后,可以开始播放视频
_controller.play('https://www.example.com/sample.mp4');
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter NimPlayer Example'),
),
body: Center(
child: NativePlayer(_controller),
),
);
}
}
3. 配置 Android 和 iOS 平台
Android
在 android/app/build.gradle
文件中,确保 minSdkVersion
至少为 21:
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
// 其他配置
}
iOS
在 ios/Podfile
中,确保 platform :ios
的版本至少为 9.0:
platform :ios, '9.0'
然后在终端中运行 pod install
来更新 iOS 项目的依赖。
4. 运行应用
确保你的设备或模拟器已连接,然后运行 flutter run
来启动应用。你应该能够看到视频播放器,并且视频开始播放。
5. 其他功能
flutter_nimplayer
还支持其他功能,例如暂停、停止、快进、快退等。你可以通过 NativePlayerController
来控制这些行为。
例如:
_controller.pause(); // 暂停播放
_controller.seekTo(Duration(seconds: 10)); // 快进到 10 秒
_controller.setVolume(0.5); // 设置音量
6. 处理错误
你还可以监听播放器的错误事件:
_controller.setErrorListener((error) {
print('An error occurred: $error');
});