Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
T
tx_player_fork
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蒋俊
tx_player_fork
Commits
add7d5d1
提交
add7d5d1
authored
2月 22, 2023
作者:
kongdywang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add offline download demo
上级
83d87594
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
35 个修改的文件
包含
931 行增加
和
182 行删除
+931
-182
CommonUtil.java
...oid/src/main/java/com/tencent/vod/flutter/CommonUtil.java
+0
-29
FTXDownloadManager.java
...main/java/com/tencent/vod/flutter/FTXDownloadManager.java
+28
-17
API文档.md
Flutter/docs/API文档.md
+287
-0
播放器组件.md
Flutter/docs/播放器组件.md
+87
-2
点播播放.md
Flutter/docs/点播播放.md
+2
-7
i18n.json
Flutter/example/assets/json/i18n.json
+18
-0
demo_download_list.dart
Flutter/example/lib/demo_download_list.dart
+0
-0
demo_superplayer.dart
Flutter/example/lib/demo_superplayer.dart
+39
-5
main.dart
Flutter/example/lib/main.dart
+12
-0
app_localization_delegate.dart
Flutter/example/lib/res/app_localization_delegate.dart
+31
-0
app_localizations.dart
Flutter/example/lib/res/app_localizations.dart
+49
-0
demo_inputdialog.dart
Flutter/example/lib/ui/demo_inputdialog.dart
+2
-2
pubspec.yaml
Flutter/example/pubspec.yaml
+4
-0
CommonUtil.h
Flutter/ios/Classes/CommonUtil.h
+0
-2
CommonUtil.m
Flutter/ios/Classes/CommonUtil.m
+0
-23
FTXDownloadManager.m
Flutter/ios/Classes/FTXDownloadManager.m
+19
-11
common_utils.dart
Flutter/lib/Core/tools/common_utils.dart
+12
-15
txplayer_define.dart
Flutter/lib/Core/txplayer_define.dart
+21
-9
txvoddownload_controller.dart
Flutter/lib/Core/txvoddownload_controller.dart
+21
-21
superplayer_ic_vod_check_done.png
...perplayer_widget/images/superplayer_ic_vod_check_done.png
+0
-0
superplayer_ic_vod_download.png
...superplayer_widget/images/superplayer_ic_vod_download.png
+0
-0
superplayer_ic_vod_download_list.png
...player_widget/images/superplayer_ic_vod_download_list.png
+0
-0
color_resource.dart
Flutter/superplayer_widget/lib/common/color_resource.dart
+11
-1
string_resource.dart
Flutter/superplayer_widget/lib/common/string_resource.dart
+9
-0
theme_resource.dart
Flutter/superplayer_widget/lib/common/theme_resource.dart
+6
-6
demo_superplayer_lib.dart
Flutter/superplayer_widget/lib/demo_superplayer_lib.dart
+3
-2
download_helper.dart
Flutter/superplayer_widget/lib/extra/download_helper.dart
+103
-0
superplayer_model.dart
Flutter/superplayer_widget/lib/model/superplayer_model.dart
+2
-0
superplayer_controller.dart
Flutter/superplayer_widget/lib/superplayer_controller.dart
+18
-3
video_quality_utils.dart
...ter/superplayer_widget/lib/tools/video_quality_utils.dart
+46
-16
superplayer_bottom_view.dart
...er/superplayer_widget/lib/ui/superplayer_bottom_view.dart
+2
-2
superplayer_more_view.dart
Flutter/superplayer_widget/lib/ui/superplayer_more_view.dart
+1
-1
superplayer_title_view.dart
...ter/superplayer_widget/lib/ui/superplayer_title_view.dart
+45
-3
superplayer_widget.dart
Flutter/superplayer_widget/lib/ui/superplayer_widget.dart
+50
-5
pubspec.yaml
Flutter/superplayer_widget/pubspec.yaml
+3
-0
没有找到文件。
Flutter/android/src/main/java/com/tencent/vod/flutter/CommonUtil.java
浏览文件 @
add7d5d1
...
...
@@ -41,35 +41,6 @@ public class CommonUtil {
return
param
;
}
/**
* 通过宽高获得对应的缓存视频清晰度
*/
public
static
int
getCacheVideoQuality
(
Integer
width
,
Integer
height
)
{
if
(
width
==
null
||
height
==
null
)
{
return
TXVodDownloadDataSource
.
QUALITY_FLU
;
}
int
minValue
=
Math
.
min
(
width
,
height
);
int
cacheQualityIndex
;
if
(
minValue
==
240
||
minValue
==
180
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_FLU
;
}
else
if
(
minValue
==
480
||
minValue
==
360
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_SD
;
}
else
if
(
minValue
==
540
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_SD
;
}
else
if
(
minValue
==
720
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_HD
;
}
else
if
(
minValue
==
1080
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_FHD
;
}
else
if
(
minValue
==
1440
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_2K
;
}
else
if
(
minValue
==
2160
)
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_4K
;
}
else
{
cacheQualityIndex
=
TXVodDownloadDataSource
.
QUALITY_UNK
;
}
return
cacheQualityIndex
;
}
public
static
int
getDownloadEventByState
(
int
mediaInfoDownloadState
)
{
Integer
event
=
DOWNLOAD_STATE_MAP
.
get
(
mediaInfoDownloadState
);
return
null
!=
event
?
event
:
FTXEvent
.
EVENT_DOWNLOAD_ERROR
;
...
...
Flutter/android/src/main/java/com/tencent/vod/flutter/FTXDownloadManager.java
浏览文件 @
add7d5d1
...
...
@@ -29,11 +29,12 @@ import io.flutter.plugin.common.MethodChannel;
* 下载管理,预下载、离线下载
*/
public
class
FTXDownloadManager
implements
MethodChannel
.
MethodCallHandler
,
ITXVodDownloadListener
{
private
FlutterPlugin
.
FlutterPluginBinding
mFlutterPluginBinding
;
private
final
MethodChannel
mMethodChannel
;
private
final
EventChannel
mEventChannel
;
private
final
FTXPlayerEventSink
mEventSink
=
new
FTXPlayerEventSink
();
private
Handler
mMainHandler
;
private
FlutterPlugin
.
FlutterPluginBinding
mFlutterPluginBinding
;
private
final
MethodChannel
mMethodChannel
;
private
final
EventChannel
mEventChannel
;
private
final
FTXPlayerEventSink
mEventSink
=
new
FTXPlayerEventSink
();
private
Handler
mMainHandler
;
/**
* 视频下载管理
...
...
@@ -108,7 +109,8 @@ public class FTXDownloadManager implements MethodChannel.MethodCallHandler, ITXV
String
videoUrl
=
call
.
argument
(
"url"
);
Integer
appId
=
call
.
argument
(
"appId"
);
String
fileId
=
call
.
argument
(
"fileId"
);
TXVodDownloadMediaInfo
mediaInfo
=
parseMediaInfoFromInfo
(
quality
,
videoUrl
,
appId
,
fileId
);
String
userName
=
call
.
argument
(
"userName"
);
TXVodDownloadMediaInfo
mediaInfo
=
parseMediaInfoFromInfo
(
quality
,
videoUrl
,
appId
,
fileId
,
userName
);
TXVodDownloadManager
.
getInstance
().
stopDownload
(
mediaInfo
);
result
.
success
(
null
);
}
else
if
(
call
.
method
.
equals
(
"setDownloadHeaders"
))
{
...
...
@@ -127,15 +129,20 @@ public class FTXDownloadManager implements MethodChannel.MethodCallHandler, ITXV
String
videoUrl
=
call
.
argument
(
"url"
);
Integer
appId
=
call
.
argument
(
"appId"
);
String
fileId
=
call
.
argument
(
"fileId"
);
TXVodDownloadMediaInfo
mediaInfo
=
parseMediaInfoFromInfo
(
quality
,
videoUrl
,
appId
,
fileId
);
String
userName
=
call
.
argument
(
"userName"
);
TXVodDownloadMediaInfo
mediaInfo
=
parseMediaInfoFromInfo
(
quality
,
videoUrl
,
appId
,
fileId
,
userName
);
result
.
success
(
buildMapFromDownloadMediaInfo
(
mediaInfo
));
}
else
if
(
call
.
method
.
equals
(
"deleteDownloadMediaInfo"
))
{
Integer
quality
=
call
.
argument
(
"quality"
);
String
videoUrl
=
call
.
argument
(
"url"
);
Integer
appId
=
call
.
argument
(
"appId"
);
String
fileId
=
call
.
argument
(
"fileId"
);
TXVodDownloadMediaInfo
mediaInfo
=
parseMediaInfoFromInfo
(
quality
,
videoUrl
,
appId
,
fileId
);
boolean
deleteResult
=
TXVodDownloadManager
.
getInstance
().
deleteDownloadMediaInfo
(
mediaInfo
);
String
userName
=
call
.
argument
(
"userName"
);
TXVodDownloadMediaInfo
mediaInfo
=
parseMediaInfoFromInfo
(
quality
,
videoUrl
,
appId
,
fileId
,
userName
);
boolean
deleteResult
=
false
;
if
(
mediaInfo
!=
null
)
{
deleteResult
=
TXVodDownloadManager
.
getInstance
().
deleteDownloadMediaInfo
(
mediaInfo
);
}
result
.
success
(
deleteResult
);
}
}
...
...
@@ -172,7 +179,7 @@ public class FTXDownloadManager implements MethodChannel.MethodCallHandler, ITXV
TXVodDownloadManager
.
getInstance
().
setListener
(
null
);
}
private
Map
<
String
,
Object
>
buildMapFromDownloadMediaInfo
(
TXVodDownloadMediaInfo
mediaInfo
)
{
private
Map
<
String
,
Object
>
buildMapFromDownloadMediaInfo
(
TXVodDownloadMediaInfo
mediaInfo
)
{
Map
<
String
,
Object
>
resultMap
=
new
HashMap
<>();
if
(
null
!=
mediaInfo
)
{
resultMap
.
put
(
"playPath"
,
mediaInfo
.
getPlayPath
());
...
...
@@ -206,8 +213,8 @@ public class FTXDownloadManager implements MethodChannel.MethodCallHandler, ITXV
bundle
.
putString
(
"userName"
,
mediaInfo
.
getUserName
());
bundle
.
putInt
(
"duration"
,
mediaInfo
.
getDuration
());
bundle
.
putInt
(
"playableDuration"
,
mediaInfo
.
getPlayableDuration
());
bundle
.
put
Int
(
"size"
,
mediaInfo
.
getSize
());
bundle
.
put
Int
(
"downloadSize"
,
mediaInfo
.
getDownloadSize
());
bundle
.
put
Long
(
"size"
,
mediaInfo
.
getSize
());
bundle
.
put
Long
(
"downloadSize"
,
mediaInfo
.
getDownloadSize
());
if
(!
TextUtils
.
isEmpty
(
mediaInfo
.
getUrl
()))
{
bundle
.
putString
(
"url"
,
mediaInfo
.
getUrl
());
}
...
...
@@ -223,18 +230,22 @@ public class FTXDownloadManager implements MethodChannel.MethodCallHandler, ITXV
}
private
TXVodDownloadMediaInfo
parseMediaInfoFromInfo
(
Integer
quality
,
String
url
,
Integer
appId
,
String
fileId
)
{
String
fileId
,
String
userName
)
{
TXVodDownloadMediaInfo
mediaInfo
=
null
;
if
(!
TextUtils
.
isEmpty
(
url
))
{
if
(
null
==
userName
)
{
userName
=
"default"
;
}
if
(
null
!=
appId
&&
null
!=
fileId
)
{
mediaInfo
=
TXVodDownloadManager
.
getInstance
()
.
getDownloadMediaInfo
(
appId
,
fileId
,
optQuality
(
quality
),
userName
);
}
else
if
(!
TextUtils
.
isEmpty
(
url
))
{
mediaInfo
=
TXVodDownloadManager
.
getInstance
().
getDownloadMediaInfo
(
url
);
}
else
if
(
null
!=
appId
&&
null
!=
fileId
)
{
mediaInfo
=
TXVodDownloadManager
.
getInstance
().
getDownloadMediaInfo
(
appId
,
fileId
,
optQuality
(
quality
));
}
return
mediaInfo
;
}
private
int
optQuality
(
Integer
quality
)
{
return
quality
==
null
?
TXVodDownloadDataSource
.
QUALITY_
FLU
:
quality
;
return
quality
==
null
?
TXVodDownloadDataSource
.
QUALITY_
UNK
:
quality
;
}
@Override
...
...
Flutter/docs/API文档.md
浏览文件 @
add7d5d1
...
...
@@ -1638,3 +1638,290 @@ Future<int> switchStream(String url) async;
| enableMessage | bool | 是否开启消息通道, 默认值为 true |
| enableMetaData | bool | 是否开启 MetaData 数据回调,默认值为 NO。 true:SDK 通过 EVT_PLAY_GET_METADATA 消息抛出视频流的 MetaData 数据;false:SDK 不抛出视频流的 MetaData 数据。 |
| flvSessionKey | String | 是否开启 HTTP 头信息回调,默认值为 “” |
## TXVodDownloadController类
### startPreLoad
**说明**
启动预下载。启动预下载前,请先设置好播放引擎的缓存目录
[
SuperPlayerPlugin.setGlobalCacheFolderPath
]
和缓存大小
[
SuperPlayerPlugin.setGlobalMaxCacheSize
]
,这个设置是全局配置需和播放器保持一致,否则会造成播放缓存失效。
**接口**
```
dart
Future
<
int
>
startPreLoad
(
final
String
playUrl
,
final
int
preloadSizeMB
,
final
int
preferredResolution
,
{
FTXPredownlodOnCompleteListener
?
onCompleteListener
,
FTXPredownlodOnErrorListener
?
onErrorListener
,
})
async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| playUrl | String | 要预下载的url|
| preloadSizeMB | int | 预下载的大小(单位:MB)|
| preferredResolution | int | 期望分辨率,值为高x宽。可参考如720
*
1080。不支持多分辨率或不需指定时,传-1|
| onCompleteListener | FTXPredownlodOnCompleteListener? | 预下载成功回调,全局|
| onErrorListener | FTXPredownlodOnErrorListener | 预下载失败回调,全局|
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| taskId | int | 任务ID |
### stopPreLoad
**说明**
停止预下载
**接口**
```
dart
Future
<
void
>
stopPreLoad
(
final
int
taskId
)
async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| taskId | int | 任务ID|
**返回值说明**
无
### startDownload
**说明**
开始下载视频
**接口**
```
dart
Future
<
void
>
startDownload
(
TXVodDownloadMediaInfo
mediaInfo
)
async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mediaInfo | TXVodDownloadMediaInfo | 下载任务信息|
**TXVodDownloadMediaInfo**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| playPath | String? | 缓存地址,获得到的视频缓存会有该值,启动下载可以不赋值|
| progress | double? | 缓存进度,获得到的视频缓存会有该值,启动下载可以不赋值|
| downloadState | int? | 缓存状态,获得到的视频缓存会有该值,启动下载可以不赋值|
| userName | String? | 下载账户名称,用于区分不同账户的下载,传空则为 default|
| duration | int? | 缓存视频总时长,安卓端单位为毫秒,IOS为秒,获得到的视频缓存会有该值,启动下载可以不赋值|
| playableDuration | int? | 视频已缓存时长,安卓端单位为毫秒,IOS为秒,获得到的视频缓存会有该值,启动下载可以不赋值|
| size | int? | 文件总大小,单位:byte,获得到的视频缓存会有该值,启动下载可以不赋值|
| downloadSize | int? | 文件已下载的大小,单位:byte,获得到的视频缓存会有该值,启动下载可以不赋值|
| url | String? | 需要下载的视频url,url下载必填,不支持嵌套m3u8和mp4下载|
| dataSource | TXVodDownloadDataSource? | 需要下载的视频fileId信息,url与该参数可只使用一个|
**TXVodDownloadDataSource**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| appId | int? | 下载文件对应的appId,必填|
| fileId | String? | 下载文件Id,必填|
| pSign | String? | 加密签名,加密视频必填|
| quality | int? | 清晰度ID,必传|
| token | String? | 加密token|
| userName | String? | 下载账户名称,用于区分不同账户的下载,传空则为 default|
**返回值说明**
无
### stopDownload
**说明**
停止下载
**接口**
```
dart
Future
<
void
>
stopDownload
(
TXVodDownloadMediaInfo
mediaInfo
)
async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mediaInfo | TXVodDownloadMediaInfo | 任务信息|
**返回值说明**
无
### setDownloadHeaders
**说明**
设置下载任务请求头
**接口**
```
dart
Future
<
void
>
setDownloadHeaders
(
Map
<
String
,
String
>
headers
)
async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| headers | Map
<String
,
String
>
| 请求头信息|
**返回值说明**
无
### getDownloadList
**说明**
获得所有下载任务,包括已下载、正在下载以及下载错误的任务
**接口**
```
dart
Future
<
List
<
TXVodDownloadMediaInfo
>>
getDownloadList
()
async
```
**参数说明**
无
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mediaInfoList | List
<TXVodDownloadMediaInfo>
| 任务列表,可通过对比userName来区分不同用户的下载|
### getDownloadInfo
**说明**
获得下载任务信息
**接口**
```
dart
Future
<
TXVodDownloadMediaInfo
>
getDownloadInfo
(
TXVodDownloadMediaInfo
mediaInfo
)
async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mediaInfo | TXVodDownloadMediaInfo | 任务信息|
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mediaInfo | TXVodDownloadMediaInfo | 缓存任务详情信息|
### setDownloadObserver
**说明**
获得下载任务信息
**接口**
```
dart
void
setDownloadObserver
(
FTXDownlodOnStateChangeListener
downlodOnStateChangeListener
,
FTXDownlodOnErrorListener
downlodOnErrorListener
)
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| downlodOnStateChangeListener | FTXDownlodOnStateChangeListener | 任务下载状态回调|
| downlodOnErrorListener | FTXDownlodOnErrorListener | 任务下载错误回调|
**返回值说明**
无
### deleteDownloadMediaInfo
**说明**
删除下载的视频
**接口**
```
dart
Future
<
bool
>
deleteDownloadMediaInfo
(
TXVodDownloadMediaInfo
mediaInfo
)
async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mediaInfo | TXVodDownloadMediaInfo | 任务下载信息|
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| result | bool | 删除结果|
### deleteDownloadMediaInfo
**说明**
删除下载的视频
**接口**
```
dart
Future
<
bool
>
deleteDownloadMediaInfo
(
TXVodDownloadMediaInfo
mediaInfo
)
async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mediaInfo | TXVodDownloadMediaInfo | 任务下载信息|
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| result | bool | 删除结果|
Flutter/docs/播放器组件.md
浏览文件 @
add7d5d1
...
...
@@ -523,7 +523,7 @@ _controller.onSimplePlayerEventBroadcast.listen((event) {
## 高级功能
### 1、通过fileId提前请求视频数据
### 1、通过fileId提前请求视频数据
[](id:fileIdPreRequest)
可通过SuperVodDataLoader提前将视频数据请求下来,提高起播速度
...
...
@@ -543,7 +543,7 @@ loader.getVideoData(model, (resultModel) {
```
### 2、画中画模式的使用
### 2、画中画模式的使用
[](id:playerPip)
#### 1、安卓平台配置
...
...
@@ -632,3 +632,88 @@ TXPipController.instance.setPipPlayerPage(this);
7.
3 随后,当用户点击SuperPlayerView上的进入画中画按钮的时候,会调用
`SuperPlayerView`
的
`_onEnterPipMode`
内部方法进入画中画,也可以自行调用
`SuperPlayerController`
的
`enterPictureInPictureMode`
方法进入。
### 3、视频下载[](id:videoDownload)
#### 1、下载视频
1.
使用播放器组件的视频下载,首先需要把SuperPlayerModel中的
`isEnableDownload`
打开,该字段默认关闭
```
dart
SuperPlayerModel
model
=
SuperPlayerModel
();
// 打开视频下载能力
model
.
isEnableDownload
=
true
;
```
播放器组件目前只会在点播播放模式下启用下载
2.
使用
`SuperPlayerController`
的
`startDownload`
方法,可以直接下载当前播放器正在播放的视频,对应的是当前播放视频的清晰度。也可是使用
`DownloadHelper`
下载指定视频,如下:
```
dart
DownloadHelper
.
instance
.
startDownloadBySize
(
videoModel
,
videoWidth
,
videoHeight
);
```
使用
`DownloadHelper`
的startDownloadBySize,可下载指定分辨率的视频,如果没有该分辨率,会下载相近分辨率的视频。
除了以上接口以外,也可选择传入画质ID或者mediaInfo直接下载。
```
dart
// 使用画质ID下载
DownloadHelper
.
instance
.
startDownload
(
videoModel
,
qualityId
);
// 使用mediaInfo下载
DownloadHelper
.
instance
.
startDownloadOrg
(
mediaInfo
);
```
3.
画质ID转换
点播的
`CommonUtils`
提供了
`getDownloadQualityBySize`
方法,用于将分辨率转为对应的画质id。
```
dart
CommonUtils
.
getDownloadQualityBySize
(
width
,
height
);
```
#### 2、停止下载视频
使用
`DownloadHelper`
的
`stopDownload`
方法可以停止对应的视频下载,示例如下:
```
dart
DownloadHelper
.
instance
.
stopDownload
(
mediaInfo
);
```
mediaInfo可通过
`DownloadHelper`
的
`getMediaInfoByCurrent`
方法获取,或者使用
`TXVodDownloadController`
的
`getDownloadList`
获得下载信息
#### 3、删除下载视频
使用
`DownloadHelper`
的
`deleteDownload`
方法,可以删除对应的视频
```
dart
bool
deleteResult
=
await
DownloadHelper
.
instance
.
deleteDownload
(
downloadModel
.
mediaInfo
);
```
deleteDownload会返回删除的结果,来判断是否删除成功
#### 4、下载状态
`DownloadHelper`
提供了基本的
`isDownloaded`
方法判断视频是否已经下载。也可以注册监听来实时判断下载状态。
`DownloadHelper`
对下载事件进行了分发,可通过如下代码进行事件注册。
```
dart
// 注册下载事件监听
DownloadHelper
.
instance
.
addDownloadListener
(
FTXDownloadListener
((
event
,
info
)
{
// 下载状态变化
},
(
errorCode
,
errorMsg
,
info
)
{
// 下载错误回调
}));
// 移除下载事件监听
DownloadHelper
.
instance
.
removeDownloadListener
(
listener
);
```
此外,还可以通过
`TXVodDownloadController.instance.getDownloadInfo(mediaInfo)`
方法或者
`TXVodDownloadController.instance.getDownloadList()`
方法直接查询mediaInfo中的downloadState来判断下载状态。
#### 5、播放下载视频
`TXVodDownloadController.instance.getDownloadInfo(mediaInfo)`
和
`TXVodDownloadController.instance.getDownloadList()`
获得到的视频信息中有个playPath字段,使用TXVodPlayerController直接播放即可
```
dart
controller
.
startVodPlay
(
mediaInfo
.
playPath
);
```
Flutter/docs/点播播放.md
浏览文件 @
add7d5d1
...
...
@@ -484,16 +484,11 @@ Fileid 下载至少需要传入 AppID、 Fileid 和 qualityId。带签名视频
**注意:加密视频只能通过Fileid下载,psign参数必须填写。**
```
dart
// QUALITY_OD // 原画
// QUALITY_FLU // 流畅
// QUALITY_SD // 标清
// QUALITY_HD // 高清
TXVodDownloadMedialnfo
medialnfo
=
TXVodDownloadMedialnfo
();
TXVodDownloadDataSource
dataSource
=
TXVodDownloadDataSource
();
dataSource
.
appId
=
1252463788
;
dataSource
.
fileId
=
"4564972819220421305"
;
dataSource
.
quality
=
DownloadQuality
.
QUALITY_
HD
;
dataSource
.
quality
=
DownloadQuality
.
QUALITY_
480P
;
dataSource
.
pSign
=
"pSignxxxx"
;
medialnfo
.
dataSource
=
dataSource
;
TXVodDownloadController
.
instance
.
startDonwload
(
medialnfo
);
...
...
@@ -574,7 +569,7 @@ medialnfo.dataSource = TXVodDownloadDataSource();
medialnfo
.
dataSource
!.
appId
=
1500005830
;
medialnfo
.
dataSource
!.
fileId
=
"8602268011437356984"
;
// fileId下载必须传入quality。quality也可以通过CommonUtils.getDownloadQualityBySize(width, height)来获取
medialnfo
.
dataSource
!.
quality
=
DownloadQuality
.
QUALITY_
HD
;
medialnfo
.
dataSource
!.
quality
=
DownloadQuality
.
QUALITY_
480P
;
TXVodDownloadMedialnfo
downloadInfo
=
await
TXVodDownloadController
.
instance
.
getDownloadInfo
(
medialnfo
);
int
?
duration
=
downloadInfo
.
duration
;
// 获取总时长
int
?
playableDuration
=
downloadInfo
.
playableDuration
;
// 获取已下载的可播放时长
...
...
Flutter/example/assets/json/i18n.json
0 → 100644
浏览文件 @
add7d5d1
{
"zh"
:
{
"player_cache_progress_label"
:
"缓存进度"
,
"player_cache_size"
:
"大小"
,
"player_download_list"
:
"下载列表"
,
"player_tip"
:
"提示"
,
"player_delete_failed"
:
"删除失败"
,
"player_caching"
:
"缓存中"
,
"player_cache_error"
:
"缓存错误"
,
"player_cache_interrupt"
:
"缓存暂停"
,
"player_cache_complete"
:
"缓存结束"
,
"player_confirm"
:
"确定"
,
"player_cancel"
:
"取消"
,
"player_check_user_delete_video"
:
"确定删除视频吗"
},
"en"
:
{}
}
\ No newline at end of file
Flutter/example/lib/demo_download_list.dart
0 → 100644
浏览文件 @
add7d5d1
差异被折叠。
点击展开。
Flutter/example/lib/demo_superplayer.dart
浏览文件 @
add7d5d1
...
...
@@ -4,6 +4,7 @@ import 'dart:async';
import
'package:flutter/material.dart'
;
import
'package:flutter_easyloading/flutter_easyloading.dart'
;
import
'package:super_player/super_player.dart'
;
import
'package:super_player_example/demo_download_list.dart'
;
import
'package:super_player_example/ui/demo_inputdialog.dart'
;
import
'package:superplayer_widget/demo_superplayer_lib.dart'
;
import
'dart:ui'
;
...
...
@@ -93,6 +94,21 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
:
AppBar
(
backgroundColor:
Colors
.
transparent
,
title:
const
Text
(
'播放器组件'
),
actions:
[
InkWell
(
onTap:
_jumpToDownloadList
,
highlightColor:
Colors
.
transparent
,
splashColor:
Colors
.
transparent
,
child:
Container
(
width:
40
,
height:
40
,
padding:
EdgeInsets
.
all
(
8
),
margin:
EdgeInsets
.
only
(
left:
8
,
right:
8
),
child:
Image
(
image:
AssetImage
(
"images/superplayer_ic_vod_download_list.png"
,
package:
StringResource
.
PKG_NAME
)),
))
],
),
body:
SafeArea
(
child:
Builder
(
...
...
@@ -108,6 +124,15 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
return
!
_controller
.
onBackPress
();
}
void
_jumpToDownloadList
()
async
{
dynamic
result
=
await
Navigator
.
push
(
context
,
MaterialPageRoute
(
builder:
(
context
)
=>
DemoDownloadList
()));
if
(
result
is
SuperPlayerModel
)
{
playVideo
(
result
);
}
else
{
print
(
"download list return result is not a videoModel, result is :
$result
"
);
}
}
Widget
getTabRow
()
{
return
new
Container
(
height:
40
,
...
...
@@ -296,6 +321,7 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
model
.
videoId
!.
fileId
=
"8602268011437356984"
;
model
.
title
=
"云点播(fileId播放)"
;
model
.
playAction
=
playAction
;
model
.
isEnableDownload
=
true
;
models
.
add
(
model
);
model
=
SuperPlayerModel
();
...
...
@@ -304,18 +330,22 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
model
.
videoId
!.
fileId
=
"5285890781763144364"
;
model
.
title
=
"腾讯云"
;
model
.
playAction
=
playAction
;
model
.
isEnableDownload
=
false
;
models
.
add
(
model
);
model
=
SuperPlayerModel
();
model
.
title
=
"加密视频播放"
;
model
.
appId
=
1
254432039
;
model
.
appId
=
1
500005830
;
model
.
videoId
=
new
SuperPlayerVideoId
();
model
.
videoId
!.
fileId
=
"
5285890816303742312
"
;
model
.
videoId
!.
fileId
=
"
243791578431393746
"
;
model
.
videoId
!.
psign
=
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6MTI1NDQzMjAzOSwiZmlsZUlkIjoiNTI4NTg5MDgxNjMwMzc0MjMxMiIsImN1cnJlbnRUaW1lU3"
"RhbXAiOjE2MTcyNTc0ODMsInBjZmciOiJiYXNpY0RybVByZXNldCIsInVybEFjY2Vzc0luZm8iOnt9LCJkcm1MaWNlbnNlSW5mbyI6e319.2H1t9dKPpdA41"
"a8t1WwI631OWC18HGl60ccBDLylCKE"
;
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6MTUwMDAwNTgzMCwiZmlsZUlkIjoiMjQzNzkxNTc4NDMxMzkzNzQ2IiwiY"
"3VycmVudFRpbWVTdGFtcCI6MTY3MzQyNjIyNywiY29udGVudEluZm8iOnsiYXVkaW9WaWRlb1R5cGUiOiJQcm90ZWN0ZWRBZGFwdGl"
"2ZSIsImRybUFkYXB0aXZlSW5mbyI6eyJwcml2YXRlRW5jcnlwdGlvbkRlZmluaXRpb24iOjEyfX0sInVybEFjY2Vzc0luZm8iOnsiZ"
"G9tYWluIjoiMTUwMDAwNTgzMC52b2QyLm15cWNsb3VkLmNvbSIsInNjaGVtZSI6IkhUVFBTIn19.q34pq7Bl0ryKDwUHGyzfXKP-C"
"DI8vrm0k_y-IaxgF_U"
;
model
.
playAction
=
playAction
;
model
.
isEnableDownload
=
true
;
models
.
add
(
model
);
model
=
SuperPlayerModel
();
...
...
@@ -323,6 +353,7 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
model
.
videoId
=
new
SuperPlayerVideoId
();
model
.
videoId
!.
fileId
=
"4564972819219071568"
;
model
.
playAction
=
playAction
;
model
.
isEnableDownload
=
false
;
models
.
add
(
model
);
model
=
SuperPlayerModel
();
...
...
@@ -330,6 +361,7 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
model
.
videoId
=
new
SuperPlayerVideoId
();
model
.
videoId
!.
fileId
=
"4564972819219071668"
;
model
.
playAction
=
playAction
;
model
.
isEnableDownload
=
false
;
models
.
add
(
model
);
model
=
SuperPlayerModel
();
...
...
@@ -337,6 +369,7 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
model
.
videoId
=
new
SuperPlayerVideoId
();
model
.
videoId
!.
fileId
=
"4564972819219071679"
;
model
.
playAction
=
playAction
;
model
.
isEnableDownload
=
false
;
models
.
add
(
model
);
model
=
SuperPlayerModel
();
...
...
@@ -344,6 +377,7 @@ class _DemoSuperPlayerState extends State<DemoSuperPlayer> with TXPipPlayerResto
model
.
videoId
=
new
SuperPlayerVideoId
();
model
.
videoId
!.
fileId
=
"4564972819219081699"
;
model
.
playAction
=
playAction
;
model
.
isEnableDownload
=
false
;
models
.
add
(
model
);
List
<
Future
<
void
>>
requestList
=
[];
...
...
Flutter/example/lib/main.dart
浏览文件 @
add7d5d1
...
...
@@ -4,8 +4,10 @@ import 'dart:async';
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_easyloading/flutter_easyloading.dart'
;
import
'package:flutter_localizations/flutter_localizations.dart'
;
import
'package:super_player/super_player.dart'
;
import
'package:super_player_example/demo_superplayer.dart'
;
import
'package:super_player_example/res/app_localization_delegate.dart'
;
import
'package:super_player_example/shortvideo/demo_short_video_lib.dart'
;
import
'package:superplayer_widget/demo_superplayer_lib.dart'
;
...
...
@@ -79,6 +81,16 @@ class _MyAppState extends State<MyApp> {
@override
Widget
build
(
BuildContext
context
)
{
return
MaterialApp
(
localizationsDelegates:
[
GlobalWidgetsLocalizations
.
delegate
,
GlobalMaterialLocalizations
.
delegate
,
GlobalCupertinoLocalizations
.
delegate
,
AppLocalizationDelegate
.
delegate
],
supportedLocales:
[
Locale
.
fromSubtags
(
languageCode:
'en'
),
Locale
.
fromSubtags
(
languageCode:
'zh'
),
],
navigatorKey:
navigatorKey
,
home:
Container
(
decoration:
BoxDecoration
(
...
...
Flutter/example/lib/res/app_localization_delegate.dart
0 → 100644
浏览文件 @
add7d5d1
// Copyright (c) 2022 Tencent. All rights reserved.
import
'package:flutter/material.dart'
;
import
'package:super_player/super_player.dart'
;
import
'package:super_player_example/res/app_localizations.dart'
;
/// 文本国际化代理
class
AppLocalizationDelegate
extends
LocalizationsDelegate
<
AppLocalizations
>
{
static
AppLocalizationDelegate
delegate
=
AppLocalizationDelegate
();
/// 设置语言支持
@override
bool
isSupported
(
Locale
locale
)
{
return
[
"zh"
,
"en"
].
contains
(
locale
.
languageCode
);
}
@override
Future
<
AppLocalizations
>
load
(
Locale
locale
)
async
{
final
appLocalizations
=
AppLocalizations
(
locale
);
await
appLocalizations
.
loadJson
();
return
appLocalizations
;
}
@override
bool
shouldReload
(
covariant
LocalizationsDelegate
<
AppLocalizations
>
old
)
{
return
false
;
}
}
\ No newline at end of file
Flutter/example/lib/res/app_localizations.dart
0 → 100644
浏览文件 @
add7d5d1
// Copyright (c) 2022 Tencent. All rights reserved.
import
'dart:convert'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
/// 文本资源国际化加载
class
AppLocalizations
{
final
Locale
locale
;
AppLocalizations
(
this
.
locale
);
static
AppLocalizations
of
(
BuildContext
context
)
{
return
Localizations
.
of
(
context
,
AppLocalizations
);
}
static
Map
<
String
,
Map
<
String
,
String
>>
_localizedStrings
=
{};
Future
<
void
>
loadJson
()
async
{
final
jsonString
=
await
rootBundle
.
loadString
(
"assets/json/i18n.json"
);
Map
<
String
,
dynamic
>
map
=
json
.
decode
(
jsonString
);
_localizedStrings
=
map
.
map
((
key
,
value
)
=>
MapEntry
(
key
,
value
.
cast
<
String
,
String
>()));
}
String
get
playerCacheProgressLabel
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_cache_progress_label"
]!;
String
get
playerDownloadList
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_download_list"
]!;
String
get
playerTip
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_tip"
]!;
String
get
playerDeleteFailed
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_delete_failed"
]!;
String
get
playerCaching
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_caching"
]!;
String
get
playerCacheError
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_cache_error"
]!;
String
get
playerCacheInterrupt
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_cache_interrupt"
]!;
String
get
playerCacheComplete
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_cache_complete"
]!;
String
get
playerConfirm
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_confirm"
]!;
String
get
playerCancel
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_cancel"
]!;
String
get
playerCheckUserDeleteVideo
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_check_user_delete_video"
]!;
String
get
playerCacheSize
=>
_localizedStrings
[
this
.
locale
.
languageCode
]![
"player_cache_size"
]!;
}
Flutter/example/lib/ui/demo_inputdialog.dart
浏览文件 @
add7d5d1
...
...
@@ -38,7 +38,7 @@ class _DemoInputDialogState extends State<DemoInputDialog> {
_buildActionWidget
(
BuildContext
context
)
{
List
<
Widget
>
actionWidgets
=
[
Fla
tButton
(
Tex
tButton
(
child:
Text
(
"确定"
),
onPressed:
()
{
Navigator
.
of
(
context
).
pop
();
...
...
@@ -52,7 +52,7 @@ class _DemoInputDialogState extends State<DemoInputDialog> {
},
// 关闭对话框
),
// Padding(padding: EdgeInsets.only(left: 15)),
Fla
tButton
(
Tex
tButton
(
child:
Text
(
"取消"
),
onPressed:
(){
Navigator
.
of
(
context
).
pop
();
...
...
Flutter/example/pubspec.yaml
浏览文件 @
add7d5d1
...
...
@@ -10,6 +10,9 @@ environment:
flutter
:
"
>=2.0.0"
dependencies
:
# 国际化
flutter_localizations
:
sdk
:
flutter
flutter
:
sdk
:
flutter
event_bus
:
^2.0.0
...
...
@@ -48,6 +51,7 @@ flutter:
# the material Icons class.
uses-material-design
:
true
assets
:
-
assets/json/
-
images/ic_new_vod_bg.png
-
images/addp.png
# To add assets to your application, add an assets section, like this:
...
...
Flutter/ios/Classes/CommonUtil.h
浏览文件 @
add7d5d1
...
...
@@ -6,8 +6,6 @@
@interface
CommonUtil
:
NSObject
+
(
NSNumber
*
)
getCacheVideoQuality
:(
int
)
width
height
:(
int
)
pHeight
;
+
(
NSNumber
*
)
getDownloadEventByState
:(
int
)
downloadState
;
@end
Flutter/ios/Classes/CommonUtil.m
浏览文件 @
add7d5d1
...
...
@@ -4,29 +4,6 @@
@implementation
CommonUtil
+
(
NSNumber
*
)
getCacheVideoQuality
:(
int
)
width
height
:(
int
)
pHeight
{
int
minValue
=
MIN
(
width
,
pHeight
);
int
cacheQualityIndex
;
if
(
minValue
==
240
||
minValue
==
180
)
{
cacheQualityIndex
=
TXVodQualityFLU
;
}
else
if
(
minValue
==
480
||
minValue
==
360
)
{
cacheQualityIndex
=
TXVodQualitySD
;
}
else
if
(
minValue
==
540
)
{
cacheQualityIndex
=
TXVodQualitySD
;
}
else
if
(
minValue
==
720
)
{
cacheQualityIndex
=
TXVodQualityHD
;
}
else
if
(
minValue
==
1080
)
{
cacheQualityIndex
=
TXVodQualityFHD
;
}
else
if
(
minValue
==
1440
)
{
cacheQualityIndex
=
TXVodQuality2K
;
}
else
if
(
minValue
==
2160
)
{
cacheQualityIndex
=
TXVodQuality4K
;
}
else
{
cacheQualityIndex
=
TXVodQualityFLU
;
}
return
[
NSNumber
numberWithInt
:
cacheQualityIndex
];
}
+
(
NSNumber
*
)
getDownloadEventByState
:(
int
)
downloadState
{
int
result
;
switch
(
downloadState
)
{
...
...
Flutter/ios/Classes/FTXDownloadManager.m
浏览文件 @
add7d5d1
...
...
@@ -93,7 +93,8 @@
NSString
*
videoUrl
=
args
[
@"url"
];
NSNumber
*
appIdNum
=
args
[
@"appId"
];
NSString
*
fileId
=
args
[
@"fileId"
];
TXVodDownloadMediaInfo
*
mediaInfo
=
[
self
parseMediaInfoFromInfo
:
quality
url
:
videoUrl
appId
:
appIdNum
fileId
:
fileId
];
NSString
*
userName
=
args
[
@"userName"
];
TXVodDownloadMediaInfo
*
mediaInfo
=
[
self
parseMediaInfoFromInfo
:
quality
url
:
videoUrl
appId
:
appIdNum
fileId
:
fileId
name
:
userName
];
[[
TXVodDownloadManager
shareInstance
]
stopDownload
:
mediaInfo
];
result
(
nil
);
}
else
if
([
@"setDownloadHeaders"
isEqualToString
:
call
.
method
])
{
...
...
@@ -111,7 +112,8 @@
NSString
*
videoUrl
=
args
[
@"url"
];
NSNumber
*
appIdNum
=
args
[
@"appId"
];
NSString
*
fileId
=
args
[
@"fileId"
];
TXVodDownloadMediaInfo
*
mediaInfo
=
[
self
parseMediaInfoFromInfo
:
quality
url
:
videoUrl
appId
:
appIdNum
fileId
:
fileId
];
NSString
*
userName
=
args
[
@"userName"
];
TXVodDownloadMediaInfo
*
mediaInfo
=
[
self
parseMediaInfoFromInfo
:
quality
url
:
videoUrl
appId
:
appIdNum
fileId
:
fileId
name
:
userName
];
NSDictionary
*
resultDic
=
[
self
buildMapFromDownloadMediaInfo
:
mediaInfo
];
result
(
resultDic
);
}
else
if
([
@"deleteDownloadMediaInfo"
isEqualToString
:
call
.
method
])
{
...
...
@@ -119,9 +121,10 @@
NSString
*
videoUrl
=
args
[
@"url"
];
NSNumber
*
appIdNum
=
args
[
@"appId"
];
NSString
*
fileId
=
args
[
@"fileId"
];
TXVodDownloadMediaInfo
*
mediaInfo
=
[
self
parseMediaInfoFromInfo
:
quality
url
:
videoUrl
appId
:
appIdNum
fileId
:
fileId
];
[[
TXVodDownloadManager
shareInstance
]
deleteDownloadMediaInfo
:
mediaInfo
];
result
(
@
(
TRUE
));
NSString
*
userName
=
args
[
@"userName"
];
TXVodDownloadMediaInfo
*
mediaInfo
=
[
self
parseMediaInfoFromInfo
:
quality
url
:
videoUrl
appId
:
appIdNum
fileId
:
fileId
name
:
userName
];
BOOL
deleteResult
=
[[
TXVodDownloadManager
shareInstance
]
deleteDownloadMediaInfo
:
mediaInfo
];
result
(
@
(
deleteResult
));
}
}
...
...
@@ -188,20 +191,25 @@
return
([
NSNull
null
]
==
(
NSNull
*
)
quality
||
nil
==
quality
)
?
TXVodQualityFLU
:
[
quality
intValue
];
}
-
(
TXVodDownloadMediaInfo
*
)
parseMediaInfoFromInfo
:
(
NSNumber
*
)
quality
url
:
(
NSString
*
)
videoUrl
appId
:
(
NSNumber
*
)
pAppId
fileId
:
(
NSString
*
)
pFileId
{
-
(
TXVodDownloadMediaInfo
*
)
parseMediaInfoFromInfo
:
(
NSNumber
*
)
quality
url
:
(
NSString
*
)
videoUrl
appId
:
(
NSNumber
*
)
pAppId
fileId
:
(
NSString
*
)
pFileId
name
:
(
NSString
*
)
name
{
TXVodDownloadMediaInfo
*
mediaInfo
=
nil
;
if
(
nil
!=
videoUrl
&&
[
NSNull
null
]
!=
(
NSNull
*
)
videoUrl
)
{
TXVodDownloadMediaInfo
*
urlInfo
=
[[
TXVodDownloadMediaInfo
alloc
]
init
];
urlInfo
.
url
=
videoUrl
;
mediaInfo
=
[[
TXVodDownloadManager
shareInstance
]
getDownloadMediaInfo
:
urlInfo
];
}
else
if
([
NSNull
null
]
!=
(
NSNull
*
)
pFileId
&&
[
NSNull
null
]
!=
(
NSNull
*
)
pAppId
)
{
if
(
name
==
nil
)
{
name
=
@"default"
;
}
if
([
NSNull
null
]
!=
(
NSNull
*
)
pFileId
&&
[
NSNull
null
]
!=
(
NSNull
*
)
pAppId
)
{
TXVodDownloadMediaInfo
*
fileIdInfo
=
[[
TXVodDownloadMediaInfo
alloc
]
init
];
TXVodDownloadDataSource
*
dataSource
=
[[
TXVodDownloadDataSource
alloc
]
init
];
dataSource
.
appId
=
[
pAppId
intValue
];
dataSource
.
fileId
=
pFileId
;;
dataSource
.
quality
=
[
self
optQuality
:
quality
];
dataSource
.
userName
=
name
;
fileIdInfo
.
dataSource
=
dataSource
;
mediaInfo
=
[[
TXVodDownloadManager
shareInstance
]
getDownloadMediaInfo
:
fileIdInfo
];
}
else
if
(
nil
!=
videoUrl
&&
[
NSNull
null
]
!=
(
NSNull
*
)
videoUrl
)
{
TXVodDownloadMediaInfo
*
urlInfo
=
[[
TXVodDownloadMediaInfo
alloc
]
init
];
urlInfo
.
url
=
videoUrl
;
urlInfo
.
userName
=
name
;
mediaInfo
=
[[
TXVodDownloadManager
shareInstance
]
getDownloadMediaInfo
:
urlInfo
];
}
return
mediaInfo
;
}
...
...
Flutter/lib/Core/tools/common_utils.dart
浏览文件 @
add7d5d1
...
...
@@ -5,24 +5,21 @@ part of SuperPlayer;
class
CommonUtils
{
/// 通过分辨率获取下载对应的qualityId
static
int
getDownloadQualityBySize
(
int
width
,
int
height
)
{
if
(
width
==
null
||
height
==
null
)
{
return
DownloadQuality
.
QUALITY_FLU
;
}
int
minValue
=
min
(
width
,
height
);
int
cacheQualityIndex
;
if
(
minValue
==
240
||
minValue
==
18
0
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
FLU
;
}
else
if
(
minValue
==
480
||
minValue
==
36
0
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
SD
;
}
else
if
(
minValue
=
=
540
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
SD
;
}
else
if
(
minValue
=
=
720
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
HD
;
}
else
if
(
minValue
=
=
1080
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
FHD
;
}
else
if
(
minValue
=
=
1440
)
{
if
(
minValue
>
0
&&
minValue
<=
24
0
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
240P
;
}
else
if
(
minValue
>
240
&&
minValue
<=
48
0
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
480P
;
}
else
if
(
minValue
>
480
&&
minValue
<
=
540
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
540P
;
}
else
if
(
minValue
>
540
&&
minValue
>
=
720
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
720P
;
}
else
if
(
minValue
>
720
&&
minValue
<
=
1080
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_
1080P
;
}
else
if
(
minValue
>
1080
&&
minValue
<
=
1440
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_2K
;
}
else
if
(
minValue
=
=
2160
)
{
}
else
if
(
minValue
>
1440
&&
minValue
<
=
2160
)
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_4K
;
}
else
{
cacheQualityIndex
=
DownloadQuality
.
QUALITY_UNK
;
...
...
Flutter/lib/Core/txplayer_define.dart
浏览文件 @
add7d5d1
...
...
@@ -209,14 +209,26 @@ class TXLogLevel {
}
class
DownloadQuality
{
@deprecated
static
const
QUALITY_OD
=
0
;
@deprecated
static
const
QUALITY_FLU
=
1
;
@deprecated
static
const
QUALITY_SD
=
2
;
@deprecated
static
const
QUALITY_HD
=
3
;
@deprecated
static
const
QUALITY_FHD
=
4
;
static
const
QUALITY_2K
=
5
;
static
const
QUALITY_4K
=
6
;
static
const
QUALITY_UNK
=
1000
;
static
const
int
QUALITY_2K
=
5
;
static
const
int
QUALITY_4K
=
6
;
static
const
int
QUALITY_UNK
=
1000
;
static
const
int
QUALITY_240P
=
240
;
static
const
int
QUALITY_360P
=
360
;
static
const
int
QUALITY_480P
=
480
;
static
const
int
QUALITY_540P
=
540
;
static
const
int
QUALITY_720P
=
720
;
static
const
int
QUALITY_1080P
=
1080
;
}
class
TXPlayInfoParams
{
...
...
@@ -264,7 +276,7 @@ class TXVodDownloadDataSource {
}
/// 视频下载信息
class
TXVodDownloadMedia
l
nfo
{
class
TXVodDownloadMedia
I
nfo
{
/// 缓存地址
String
?
playPath
;
/// 下载进度
...
...
@@ -291,6 +303,9 @@ class TXVodDownloadMedialnfo {
Map
<
String
,
dynamic
>
toJson
()
{
Map
<
String
,
dynamic
>
json
=
{};
if
(
null
!=
dataSource
)
{
json
.
addAll
(
dataSource
!.
toJson
());
}
json
[
"url"
]
=
url
;
json
[
"downloadState"
]
=
downloadState
;
json
[
"progress"
]
=
progress
;
...
...
@@ -300,9 +315,6 @@ class TXVodDownloadMedialnfo {
json
[
"playableDuration"
]
=
playableDuration
;
json
[
"size"
]
=
size
;
json
[
"downloadSize"
]
=
downloadSize
;
if
(
null
!=
dataSource
)
{
json
.
addAll
(
dataSource
!.
toJson
());
}
return
json
;
}
}
...
...
@@ -319,6 +331,6 @@ abstract class TXPlayerType {
typedef
FTXPredownlodOnCompleteListener
=
void
Function
(
int
taskId
,
String
url
);
typedef
FTXPredownlodOnErrorListener
=
void
Function
(
int
taskId
,
String
url
,
int
code
,
String
msg
);
// 视频下载时间回调Listener
typedef
FTXDownlodOnStateChangeListener
=
void
Function
(
int
event
,
TXVodDownloadMedia
l
nfo
info
);
typedef
FTXDownlodOnErrorListener
=
void
Function
(
int
errorCode
,
String
errorMsg
,
TXVodDownloadMedia
l
nfo
info
);
typedef
FTXDownlodOnStateChangeListener
=
void
Function
(
int
event
,
TXVodDownloadMedia
I
nfo
info
);
typedef
FTXDownlodOnErrorListener
=
void
Function
(
int
errorCode
,
String
errorMsg
,
TXVodDownloadMedia
I
nfo
info
);
Flutter/lib/Core/txvoddownload_controller.dart
浏览文件 @
add7d5d1
...
...
@@ -24,12 +24,12 @@ class TXVodDownloadController {
static
TXVodDownloadController
_sharedInstance
()
{
if
(
_instance
==
null
)
{
_instance
=
TXVodDownloadController
.
_createIns
at
nce
();
_instance
=
TXVodDownloadController
.
_createIns
ta
nce
();
}
return
_instance
!;
}
TXVodDownloadController
.
_createIns
at
nce
()
{
TXVodDownloadController
.
_createIns
ta
nce
()
{
EventChannel
eventChannel
=
EventChannel
(
"cloud.tencent.com/txvodplayer/download/event"
);
_downloadEventSubscription
=
eventChannel
.
receiveBroadcastStream
(
'event'
).
listen
(
_eventHandler
,
onError:
_errorHandler
);
...
...
@@ -65,16 +65,16 @@ class TXVodDownloadController {
}
/// 开始下载
/// videoDownloadModel: 下载构造体 [TXVodDownloadMedia
l
nfo]
/// videoDownloadModel: 下载构造体 [TXVodDownloadMedia
I
nfo]
/// userName: 下载用户,用来区分不同用户的下载,可不传,不传则使用默认值
Future
<
void
>
startDo
nwload
(
TXVodDownloadMedialnfo
medial
nfo
)
async
{
await
_methodChannel
.
invokeMethod
(
"startDownload"
,
media
l
nfo
.
toJson
());
Future
<
void
>
startDo
wnload
(
TXVodDownloadMediaInfo
mediaI
nfo
)
async
{
await
_methodChannel
.
invokeMethod
(
"startDownload"
,
media
I
nfo
.
toJson
());
}
/// 停止下载
/// videoDownloadModel: 下载构造体 [TXVodDownloadMedia
l
nfo]
Future
<
void
>
stopDownload
(
TXVodDownloadMedia
lnfo
medial
nfo
)
async
{
await
_methodChannel
.
invokeMethod
(
"stopDownload"
,
media
l
nfo
.
toJson
());
/// videoDownloadModel: 下载构造体 [TXVodDownloadMedia
I
nfo]
Future
<
void
>
stopDownload
(
TXVodDownloadMedia
Info
mediaI
nfo
)
async
{
await
_methodChannel
.
invokeMethod
(
"stopDownload"
,
media
I
nfo
.
toJson
());
}
/// 设置下载请求头
...
...
@@ -83,9 +83,9 @@ class TXVodDownloadController {
}
/// 获取所有视频下载列表
/// return [TXVodDownloadMedia
l
nfo]
Future
<
List
<
TXVodDownloadMedia
l
nfo
>>
getDownloadList
()
async
{
List
<
TXVodDownloadMedia
l
nfo
>
outputList
=
[];
/// return [TXVodDownloadMedia
I
nfo]
Future
<
List
<
TXVodDownloadMedia
I
nfo
>>
getDownloadList
()
async
{
List
<
TXVodDownloadMedia
I
nfo
>
outputList
=
[];
List
<
dynamic
>
donwloadOrgList
=
await
_methodChannel
.
invokeMethod
(
"getDownloadList"
);
for
(
dynamic
data
in
donwloadOrgList
)
{
outputList
.
add
(
_getDownloadInfoFromMap
(
data
));
...
...
@@ -94,26 +94,26 @@ class TXVodDownloadController {
}
/// 获得指定视频的下载信息
/// return [TXVodDownloadMedia
l
nfo]
Future
<
TXVodDownloadMedia
lnfo
>
getDownloadInfo
(
TXVodDownloadMedialnfo
medial
nfo
)
async
{
Map
<
dynamic
,
dynamic
>
data
=
await
_methodChannel
.
invokeMethod
(
"getDownloadInfo"
,
media
l
nfo
.
toJson
());
/// return [TXVodDownloadMedia
I
nfo]
Future
<
TXVodDownloadMedia
Info
>
getDownloadInfo
(
TXVodDownloadMediaInfo
mediaI
nfo
)
async
{
Map
<
dynamic
,
dynamic
>
data
=
await
_methodChannel
.
invokeMethod
(
"getDownloadInfo"
,
media
I
nfo
.
toJson
());
return
_getDownloadInfoFromMap
(
data
);
}
/// 设置下载事件监听,该监听为全局下载监听配置,重复调用
,listener会先后覆盖
/// 设置下载事件监听,该监听为全局下载监听配置,重复调用
void
setDownloadObserver
(
FTXDownlodOnStateChangeListener
downlodOnStateChangeListener
,
FTXDownlodOnErrorListener
downlodOnErrorListener
)
{
FTXDownlodOnStateChangeListener
?
downlodOnStateChangeListener
,
FTXDownlodOnErrorListener
?
downlodOnErrorListener
)
{
_downlodOnStateChangeListener
=
downlodOnStateChangeListener
;
_downlodOnErrorListener
=
downlodOnErrorListener
;
}
/// 删除下载任务
Future
<
bool
>
deleteDownloadMediaInfo
(
TXVodDownloadMedia
lnfo
medial
nfo
)
async
{
return
await
_methodChannel
.
invokeMethod
(
"deleteDownloadMediaInfo"
,
media
l
nfo
.
toJson
());
Future
<
bool
>
deleteDownloadMediaInfo
(
TXVodDownloadMedia
Info
mediaI
nfo
)
async
{
return
await
_methodChannel
.
invokeMethod
(
"deleteDownloadMediaInfo"
,
media
I
nfo
.
toJson
());
}
TXVodDownloadMedia
l
nfo
_getDownloadInfoFromMap
(
Map
<
dynamic
,
dynamic
>
map
)
{
TXVodDownloadMedia
lnfo
medialnfo
=
TXVodDownloadMedial
nfo
();
TXVodDownloadMedia
I
nfo
_getDownloadInfoFromMap
(
Map
<
dynamic
,
dynamic
>
map
)
{
TXVodDownloadMedia
Info
medialnfo
=
TXVodDownloadMediaI
nfo
();
medialnfo
.
playPath
=
map
[
"playPath"
];
medialnfo
.
progress
=
map
[
"progress"
];
medialnfo
.
downloadState
=
map
[
"downloadState"
];
...
...
@@ -169,7 +169,7 @@ class TXVodDownloadController {
_downlodOnStateChangeListener
?.
call
(
eventCode
,
_getDownloadInfoFromMap
(
map
));
break
;
case
TXVodPlayEvent
.
EVENT_DOWNLOAD_ERROR
:
TXVodDownloadMedia
l
nfo
info
=
_getDownloadInfoFromMap
(
map
);
TXVodDownloadMedia
I
nfo
info
=
_getDownloadInfoFromMap
(
map
);
int
errorCode
=
map
[
"errorCode"
];
String
errorMsg
=
map
[
"errorMsg"
];
_downlodOnErrorListener
?.
call
(
errorCode
,
errorMsg
,
info
);
...
...
Flutter/superplayer_widget/images/superplayer_ic_vod_check_done.png
0 → 100644
浏览文件 @
add7d5d1
1.5 KB
Flutter/superplayer_widget/images/superplayer_ic_vod_download.png
0 → 100644
浏览文件 @
add7d5d1
472 Bytes
Flutter/superplayer_widget/images/superplayer_ic_vod_download_list.png
0 → 100644
浏览文件 @
add7d5d1
556 Bytes
Flutter/superplayer_widget/lib/common/color_resource.dart
浏览文件 @
add7d5d1
...
...
@@ -2,9 +2,18 @@
part of
demo_super_player_lib
;
/// colors resource
class
ColorResource
{
static
const
COLOR_MAIN_THEME
=
0xFFFF4C58
;
static
const
COLOR_SLIDER_MAIN_THEME
=
0xFFFF4C58
;
static
const
COLOR_APP_MAIN_THEME
=
0xFF14233D
;
static
const
COLOR_GRAY
=
0xFFBBBBBB
;
static
const
COLOR_TRANS_BLACK
=
0xBB000000
;
static
const
COLOR_WHITE
=
0xFFFFFFFF
;
static
const
COLOR_TRANS_GRAY
=
0x11BBBBBB
;
static
const
COLOR_TRANS_GRAY_2
=
0x33DDDDDD
;
static
const
COLOR_TRANS_GRAY_3
=
0xFFA3A8B1
;
static
const
COLOR_TRANS_GRAY_4
=
0xFF787878
;
static
const
COLOR_BTN_BULUE
=
0xFF2065DA
;
static
const
COLOR_DOWNLOAD_CACHING
=
0xFFDD9322
;
static
const
COLOR_DOWNLOAD_COMPELETE
=
0xFF20C86F
;
static
const
COLOR_DOWNLOAD_INTERUPT
=
0xFFFD7657
;
}
\ No newline at end of file
Flutter/superplayer_widget/lib/common/string_resource.dart
浏览文件 @
add7d5d1
...
...
@@ -9,8 +9,15 @@ class StringResource {
static
const
QUALITY_FSD
=
"全标清"
;
static
const
QUALITY_FHD
=
"全高清"
;
static
const
QUALITY_FHD2
=
"超清"
;
static
const
QUALITY_240P
=
"流畅240p"
;
static
const
QUALITY_360P
=
"流畅360p"
;
static
const
QUALITY_480P
=
"标清480p"
;
static
const
QUALITY_540P
=
"标清540p"
;
static
const
QUALITY_720P
=
"高清720p"
;
static
const
QUALITY_1080P
=
"全高清1080p"
;
static
const
QUALITY_2K
=
"2K"
;
static
const
QUALITY_4K
=
"4k"
;
static
const
QUALITY_OD
=
"原画"
;
static
const
VOICE_LABEL
=
"声音"
;
static
const
BRIGHTNESS_LABEL
=
"亮度"
;
...
...
@@ -22,4 +29,6 @@ class StringResource {
static
const
ERROR_PIP
=
"画中画开启失败"
;
static
const
PKG_NAME
=
"superplayer_widget"
;
static
const
TEST_VIDEO_TITLE
=
"测试视频"
;
}
Flutter/superplayer_widget/lib/common/theme_resource.dart
浏览文件 @
add7d5d1
...
...
@@ -8,11 +8,11 @@ class ThemeResource {
return
ThemeData
(
sliderTheme:
SliderThemeData
(
trackHeight:
2
,
thumbColor:
Color
(
ColorResource
.
COLOR_MAIN_THEME
),
thumbColor:
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
),
thumbShape:
RoundSliderThumbShape
(
enabledThumbRadius:
4
),
overlayColor:
Colors
.
white
,
overlayShape:
RoundSliderOverlayShape
(
overlayRadius:
10
),
activeTrackColor:
Color
(
ColorResource
.
COLOR_MAIN_THEME
),
activeTrackColor:
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
),
inactiveTrackColor:
Color
(
ColorResource
.
COLOR_GRAY
),
));
}
...
...
@@ -22,12 +22,12 @@ class ThemeResource {
return
ThemeData
(
sliderTheme:
SliderThemeData
(
trackHeight:
1
,
thumbColor:
Color
(
ColorResource
.
COLOR_MAIN_THEME
),
thumbColor:
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
),
thumbShape:
RoundSliderThumbShape
(
enabledThumbRadius:
0
,
disabledThumbRadius:
0
,
elevation:
0
,
pressedElevation:
0
),
overlayColor:
Colors
.
white
,
overlayShape:
RoundSliderOverlayShape
(
overlayRadius:
1
),
activeTrackColor:
Color
(
ColorResource
.
COLOR_MAIN_THEME
),
activeTrackColor:
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
),
inactiveTrackColor:
Color
(
ColorResource
.
COLOR_GRAY
),
));
}
...
...
@@ -37,7 +37,7 @@ class ThemeResource {
}
static
TextStyle
getCheckedLabelTextStyle
()
{
return
TextStyle
(
fontSize:
14
,
color:
Color
(
ColorResource
.
COLOR_MAIN_THEME
));
return
TextStyle
(
fontSize:
14
,
color:
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
));
}
static
TextStyle
getCommonTextStyle
()
{
...
...
@@ -45,6 +45,6 @@ class ThemeResource {
}
static
TextStyle
getCheckedTextStyle
()
{
return
TextStyle
(
fontSize:
13
,
color:
Color
(
ColorResource
.
COLOR_MAIN_THEME
));
return
TextStyle
(
fontSize:
13
,
color:
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
));
}
}
Flutter/superplayer_widget/lib/demo_superplayer_lib.dart
浏览文件 @
add7d5d1
...
...
@@ -39,4 +39,5 @@ part 'ui/superplayer_video_slider.dart';
part
'common/color_resource.dart'
;
part
'common/string_resource.dart'
;
part
'common/theme_resource.dart'
;
part
'common/task_executors.dart'
;
\ No newline at end of file
part
'common/task_executors.dart'
;
part
'extra/download_helper.dart'
;
\ No newline at end of file
Flutter/superplayer_widget/lib/extra/download_helper.dart
0 → 100644
浏览文件 @
add7d5d1
// Copyright (c) 2022 Tencent. All rights reserved.
part of
demo_super_player_lib
;
/// 下载帮助类,配合播放器组件使用,简化下载使用流程
class
DownloadHelper
{
static
DownloadHelper
?
_instance
;
static
DownloadHelper
get
instance
=>
_sharedInstance
();
/// SuperPlayerPlugin单例
static
DownloadHelper
_sharedInstance
()
{
_instance
??=
DownloadHelper
.
_internal
();
return
_instance
!;
}
final
List
<
FTXDownloadListener
>
_listeners
=
[];
/// 初始model
DownloadHelper
.
_internal
()
{
TXVodDownloadController
.
instance
.
setDownloadObserver
((
event
,
info
)
{
for
(
FTXDownloadListener
listener
in
_listeners
)
{
listener
.
onStateChangeListener
(
event
,
info
);
}
},
(
errorCode
,
errorMsg
,
info
)
{
for
(
FTXDownloadListener
listener
in
_listeners
)
{
listener
.
onErrorListener
(
errorCode
,
errorMsg
,
info
);
}
});
}
void
addDownloadListener
(
FTXDownloadListener
listener
)
{
if
(!
_listeners
.
contains
(
listener
))
{
_listeners
.
add
(
listener
);
}
}
void
removeDownloadListener
(
FTXDownloadListener
listener
)
{
_listeners
.
remove
(
listener
);
}
void
clearListener
()
{
_listeners
.
clear
();
}
/// 根据videoModel生成下载MediaInfo
TXVodDownloadMediaInfo
getMediaInfoByCurrent
(
SuperPlayerModel
?
model
,
int
qualityId
)
{
TXVodDownloadMediaInfo
mediaInfo
=
TXVodDownloadMediaInfo
();
if
(
null
!=
model
)
{
if
(
model
.
videoId
!=
null
)
{
TXVodDownloadDataSource
dataSource
=
TXVodDownloadDataSource
();
dataSource
.
appId
=
model
.
appId
;
dataSource
.
fileId
=
model
.
videoId
!.
fileId
;
dataSource
.
pSign
=
model
.
videoId
!.
psign
;
dataSource
.
quality
=
qualityId
;
dataSource
.
userName
=
"default"
;
mediaInfo
.
dataSource
=
dataSource
;
}
else
{
mediaInfo
.
url
=
model
.
videoURL
;
}
// 下载会按照userName区分不同用户的下载,这里给了一个默认用户
mediaInfo
.
userName
=
"default"
;
}
return
mediaInfo
;
}
Future
<
bool
>
isDownloaded
(
SuperPlayerModel
?
model
,
int
width
,
int
height
)
async
{
TXVodDownloadMediaInfo
mediaInfo
=
getMediaInfoByCurrent
(
model
,
VideoQualityUtils
.
getCacheVideoQualityIndex
(
width
,
height
));
TXVodDownloadMediaInfo
cacheInfo
=
await
TXVodDownloadController
.
instance
.
getDownloadInfo
(
mediaInfo
);
return
cacheInfo
.
downloadState
==
TXVodPlayEvent
.
EVENT_DOWNLOAD_FINISH
;
}
Future
<
void
>
startDownloadBySize
(
SuperPlayerModel
?
model
,
int
width
,
int
height
)
async
{
return
startDownload
(
model
,
VideoQualityUtils
.
getCacheVideoQualityIndex
(
width
,
height
));
}
Future
<
void
>
startDownload
(
SuperPlayerModel
?
model
,
int
qualityId
)
async
{
return
TXVodDownloadController
.
instance
.
startDownload
(
getMediaInfoByCurrent
(
model
,
qualityId
));
}
Future
<
void
>
startDownloadOrg
(
TXVodDownloadMediaInfo
mediaInfo
)
async
{
return
TXVodDownloadController
.
instance
.
startDownload
(
mediaInfo
);
}
Future
<
bool
>
deleteDownload
(
TXVodDownloadMediaInfo
mediaInfo
)
async
{
return
TXVodDownloadController
.
instance
.
deleteDownloadMediaInfo
(
mediaInfo
);
}
Future
<
void
>
stopDownload
(
TXVodDownloadMediaInfo
mediaInfo
)
async
{
return
TXVodDownloadController
.
instance
.
stopDownload
(
mediaInfo
);
}
void
destroy
()
{
TXVodDownloadController
.
instance
.
setDownloadObserver
(
null
,
null
);
}
}
class
FTXDownloadListener
{
final
FTXDownlodOnStateChangeListener
onStateChangeListener
;
final
FTXDownlodOnErrorListener
onErrorListener
;
FTXDownloadListener
(
this
.
onStateChangeListener
,
this
.
onErrorListener
);
}
Flutter/superplayer_widget/lib/model/superplayer_model.dart
浏览文件 @
add7d5d1
...
...
@@ -84,6 +84,8 @@ class SuperPlayerModel {
String
coverUrl
=
""
;
// coverUrl from net
String
customeCoverUrl
=
""
;
// custome video cover image
int
duration
=
0
;
// video duration
// 是否启用下载能力,默认关闭
bool
isEnableDownload
=
false
;
// feed流视频描述
String
videoDescription
=
""
;
...
...
Flutter/superplayer_widget/lib/superplayer_controller.dart
浏览文件 @
add7d5d1
...
...
@@ -22,7 +22,7 @@ class SuperPlayerController {
PlayInfoProtocol
?
_currentProtocol
;
_SuperPlayerObserver
?
_observer
;
VideoQuality
?
currentQuality
;
List
<
VideoQuality
>?
currentQualiyList
;
List
<
VideoQuality
>?
currentQuali
t
yList
;
StreamController
<
TXPlayerHolder
>
playerStreamController
=
StreamController
.
broadcast
();
SuperPlayerState
playerState
=
SuperPlayerState
.
INIT
;
SuperPlayerType
playerType
=
SuperPlayerType
.
VOD
;
...
...
@@ -57,6 +57,7 @@ class SuperPlayerController {
double
_seekPos
=
0
;
// 记录切换硬解时的播放时间
/// 该值会改变新播放视频的播放开始时间点
double
startPos
=
0
;
/// 播放器内核解析出来的视频宽高
double
videoWidth
=
0
;
double
videoHeight
=
0
;
...
...
@@ -254,6 +255,18 @@ class SuperPlayerController {
}
}
Future
<
bool
>
isDownloaded
()
async
{
if
(
videoWidth
==
0
||
videoHeight
==
0
)
{
return
false
;
}
else
{
return
await
DownloadHelper
.
instance
.
isDownloaded
(
videoModel
,
videoWidth
.
toInt
(),
videoHeight
.
toInt
());
}
}
void
startDownload
()
{
DownloadHelper
.
instance
.
startDownloadBySize
(
videoModel
,
videoWidth
.
toInt
(),
videoHeight
.
toInt
());
}
/// 播放视频.
/// 10.7版本开始,playWithModel变更为playWithModelNeedLicence,需要通过 {@link SuperPlayerPlugin#setGlobalLicense} 设置 Licence 后方可成功播放,
/// 否则将播放失败(黑屏),全局仅设置一次即可。直播 Licence、短视频 Licence 和视频播放 Licence 均可使用,若您暂未获取上述 Licence ,
...
...
@@ -573,7 +586,7 @@ class SuperPlayerController {
void
_updateVideoQualityList
(
List
<
VideoQuality
>?
qualityList
,
VideoQuality
?
defaultQuality
)
{
currentQuality
=
defaultQuality
;
currentQualiyList
=
qualityList
;
currentQuali
t
yList
=
qualityList
;
_observer
?.
onVideoQualityListChange
(
qualityList
,
defaultQuality
);
}
...
...
@@ -610,10 +623,12 @@ class SuperPlayerController {
isPrepared
=
false
;
_needToResume
=
false
;
_needToPause
=
false
;
videoWidth
=
0
;
videoHeight
=
0
;
currentDuration
=
0
;
videoDuration
=
0
;
currentQuality
=
null
;
currentQualiyList
?.
clear
();
currentQuali
t
yList
?.
clear
();
_currentProtocol
=
null
;
// 移除所有事件
_vodPlayEventListener
?.
cancel
();
...
...
Flutter/superplayer_widget/lib/tools/video_quality_utils.dart
浏览文件 @
add7d5d1
...
...
@@ -4,6 +4,22 @@ part of demo_super_player_lib;
/// video quality utils
class
VideoQualityUtils
{
static
const
TAG
=
"VideoQualityUtils"
;
static
const
Map
<
int
,
String
>
downloadQualityMap
=
{
DownloadQuality
.
QUALITY_FLU
:
StringResource
.
QUALITY_FLU
,
DownloadQuality
.
QUALITY_SD
:
StringResource
.
QUALITY_SD
,
DownloadQuality
.
QUALITY_HD
:
StringResource
.
QUALITY_HD
,
DownloadQuality
.
QUALITY_FHD
:
StringResource
.
QUALITY_FHD
,
DownloadQuality
.
QUALITY_OD
:
StringResource
.
QUALITY_OD
,
DownloadQuality
.
QUALITY_240P
:
StringResource
.
QUALITY_240P
,
DownloadQuality
.
QUALITY_360P
:
StringResource
.
QUALITY_360P
,
DownloadQuality
.
QUALITY_480P
:
StringResource
.
QUALITY_480P
,
DownloadQuality
.
QUALITY_540P
:
StringResource
.
QUALITY_540P
,
DownloadQuality
.
QUALITY_720P
:
StringResource
.
QUALITY_720P
,
DownloadQuality
.
QUALITY_1080P
:
StringResource
.
QUALITY_1080P
,
DownloadQuality
.
QUALITY_2K
:
StringResource
.
QUALITY_2K
,
DownloadQuality
.
QUALITY_4K
:
StringResource
.
QUALITY_4K
,
DownloadQuality
.
QUALITY_UNK
:
""
,
};
/// convert to quality by transcodePlayList
static
List
<
VideoQuality
>
convertToVideoQualityList
(
Map
<
String
,
PlayInfoStream
>
transcodePlayList
)
{
...
...
@@ -18,7 +34,7 @@ class VideoQualityUtils {
/// convert to quality by PlayInfoStream
static
VideoQuality
convertToVideoQuality
(
PlayInfoStream
stream
)
{
VideoQuality
quality
=
new
VideoQuality
();
VideoQuality
quality
=
VideoQuality
();
quality
.
bitrate
=
stream
.
bitrate
;
quality
.
name
=
stream
.
id
;
quality
.
title
=
stream
.
name
;
...
...
@@ -29,41 +45,43 @@ class VideoQualityUtils {
/// convert to quality by FTXBitrateItem
static
VideoQuality
convertToVideoQualityByBitrate
(
BuildContext
context
,
FTXBitrateItem
bitrateItem
)
{
VideoQuality
quality
=
new
VideoQuality
();
VideoQuality
quality
=
VideoQuality
();
quality
.
bitrate
=
bitrateItem
.
bitrate
;
quality
.
index
=
bitrateItem
.
index
;
quality
.
height
=
bitrateItem
.
height
;
quality
.
width
=
bitrateItem
.
width
;
formatVideoQuality
(
quality
);
quality
.
title
=
formatVideoQuality
(
quality
.
width
,
quality
.
height
);
return
quality
;
}
/// format quality title by size
static
void
formatVideoQuality
(
VideoQuality
quality
)
{
int
minValue
=
min
(
quality
.
width
,
quality
.
height
);
static
String
formatVideoQuality
(
int
width
,
int
height
)
{
int
minValue
=
min
(
width
,
height
);
String
title
=
" (
${minValue}
dp)"
;
if
(
minValue
==
240
||
minValue
==
180
)
{
quality
.
title
=
"
${StringResource.QUALITY_FLU}
(
${minValue}
dp)"
;
}
else
if
(
minValue
==
480
||
minValue
==
360
)
{
quality
.
title
=
"
${StringResource.QUALITY_SD}
(
${minValue}
dp)"
;
title
=
StringResource
.
QUALITY_240P
;
}
else
if
(
minValue
==
360
)
{
title
=
StringResource
.
QUALITY_360P
;
}
else
if
(
minValue
==
480
)
{
title
=
StringResource
.
QUALITY_480P
;
}
else
if
(
minValue
==
540
)
{
quality
.
title
=
"
${StringResource.QUALITY_FSD}
(
${minValue}
dp)"
;
title
=
StringResource
.
QUALITY_540P
;
}
else
if
(
minValue
==
720
)
{
quality
.
title
=
"
${StringResource.QUALITY_HD}
(
${minValue}
dp)"
;
title
=
StringResource
.
QUALITY_720P
;
}
else
if
(
minValue
==
1080
)
{
quality
.
title
=
"
${StringResource.QUALITY_FHD2}
(
${minValue}
dp)"
;
title
=
StringResource
.
QUALITY_1080P
;
}
else
if
(
minValue
==
1440
)
{
quality
.
title
=
"
${StringResource.QUALITY_2K}
(
${minValue}
dp)"
;
title
=
StringResource
.
QUALITY_2K
;
}
else
if
(
minValue
==
2160
)
{
quality
.
title
=
"
${StringResource.QUALITY_4K}
(
${minValue}
dp)"
;
}
else
{
quality
.
title
=
" (
${minValue}
dp)"
;
title
=
StringResource
.
QUALITY_4K
;
}
return
title
;
}
/// convert to quality by FTXBitrateItem and resolutionNames
static
VideoQuality
convertToVideoQualityByResolution
(
FTXBitrateItem
bitrateItem
,
List
<
ResolutionName
>
resolutionNames
)
{
VideoQuality
quality
=
new
VideoQuality
();
VideoQuality
quality
=
VideoQuality
();
quality
.
bitrate
=
bitrateItem
.
bitrate
;
quality
.
index
=
bitrateItem
.
index
;
bool
getName
=
false
;
...
...
@@ -94,4 +112,16 @@ class VideoQualityUtils {
}
return
qualityName
;
}
/// 根据videoQuality,转化为视频下载需要用到的画质id
/// @param width 宽度
/// @param height 高度
/// @return [DownloadQuality];
static
int
getCacheVideoQualityIndex
(
int
width
,
int
height
)
{
return
CommonUtils
.
getDownloadQualityBySize
(
width
,
height
);
}
static
String
getNameByCacheQualityId
(
int
cacheQualityId
)
{
return
downloadQualityMap
[
cacheQualityId
]
??
""
;
}
}
Flutter/superplayer_widget/lib/ui/superplayer_bottom_view.dart
浏览文件 @
add7d5d1
...
...
@@ -167,9 +167,9 @@ class _VideoBottomViewState extends State<VideoBottomView> {
max:
_videoDuration
,
value:
_currentDuration
,
bufferedValue:
_bufferedDuration
,
activeColor:
const
Color
(
ColorResource
.
COLOR_MAIN_THEME
),
activeColor:
const
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
),
inactiveColor:
const
Color
(
ColorResource
.
COLOR_GRAY
),
sliderColor:
const
Color
(
ColorResource
.
COLOR_MAIN_THEME
),
sliderColor:
const
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
),
sliderOutterColor:
Colors
.
white
,
progressHeight:
2
,
sliderRadius:
4
,
...
...
Flutter/superplayer_widget/lib/ui/superplayer_more_view.dart
浏览文件 @
add7d5d1
...
...
@@ -117,7 +117,7 @@ class _SuperPlayerMoreViewState extends State<SuperPlayerMoreView> {
style:
ThemeResource
.
getCommonLabelTextStyle
(),
),
Switch
(
activeColor:
const
Color
(
ColorResource
.
COLOR_MAIN_THEME
),
activeColor:
const
Color
(
ColorResource
.
COLOR_
SLIDER_
MAIN_THEME
),
value:
_isOpenAccelerate
,
onChanged:
_onChangeAccelerate
)
],
...
...
Flutter/superplayer_widget/lib/ui/superplayer_title_view.dart
浏览文件 @
add7d5d1
...
...
@@ -5,8 +5,11 @@ class _VideoTitleView extends StatefulWidget {
final
String
_title
;
final
_VideoTitleController
_controller
;
final
bool
initIsFullScreen
;
final
bool
showDownload
;
final
bool
isDownloaded
;
const
_VideoTitleView
(
this
.
_controller
,
this
.
initIsFullScreen
,
this
.
_title
,
GlobalKey
<
_VideoTitleViewState
>
key
)
const
_VideoTitleView
(
this
.
_controller
,
this
.
initIsFullScreen
,
this
.
_title
,
this
.
showDownload
,
this
.
isDownloaded
,
GlobalKey
<
_VideoTitleViewState
>
key
)
:
super
(
key:
key
);
@override
...
...
@@ -34,6 +37,7 @@ class _VideoTitleViewState extends State<_VideoTitleView> {
fit:
BoxFit
.
fill
)),
child:
Row
(
children:
[
// back
InkWell
(
onTap:
_onTapBackBtn
,
child:
const
Image
(
...
...
@@ -42,11 +46,42 @@ class _VideoTitleViewState extends State<_VideoTitleView> {
image:
AssetImage
(
"images/superplayer_btn_back_play.png"
,
package:
StringResource
.
PKG_NAME
),
),
),
// video name
Text
(
_title
,
style:
const
TextStyle
(
fontSize:
11
,
color:
Colors
.
white
),
),
const
Expanded
(
child:
SizedBox
()),
const
Expanded
(
child:
SizedBox
()),
//
// download
Visibility
(
visible:
_isFullScreen
&&
widget
.
showDownload
,
child:
InkWell
(
onTap:
_onTapDownload
,
child:
Container
(
padding:
const
EdgeInsets
.
all
(
8
),
margin:
const
EdgeInsets
.
only
(
left:
8
,
right:
8
),
width:
40
,
height:
40
,
child:
Stack
(
children:
[
const
Image
(
image:
AssetImage
(
"images/superplayer_ic_vod_download.png"
,
package:
StringResource
.
PKG_NAME
)),
Visibility
(
visible:
widget
.
isDownloaded
,
child:
const
Positioned
(
right:
0
,
bottom:
0
,
child:
Image
(
width:
12
,
height:
12
,
image:
AssetImage
(
"images/superplayer_ic_vod_check_done.png"
,
package:
StringResource
.
PKG_NAME
))))
],
),
),
),
),
// more menu
Visibility
(
visible:
_isFullScreen
,
child:
InkWell
(
...
...
@@ -70,6 +105,12 @@ class _VideoTitleViewState extends State<_VideoTitleView> {
widget
.
_controller
.
_onTapBack
();
}
void
_onTapDownload
()
{
if
(!
widget
.
isDownloaded
)
{
widget
.
_controller
.
_onTapDownload
();
}
}
void
updateTitle
(
String
name
)
{
if
(
mounted
)
{
setState
(()
{
...
...
@@ -88,6 +129,7 @@ class _VideoTitleViewState extends State<_VideoTitleView> {
class
_VideoTitleController
{
final
Function
_onTapBack
;
final
Function
_onTapMore
;
final
Function
_onTapDownload
;
_VideoTitleController
(
this
.
_onTapBack
,
this
.
_onTapMore
);
_VideoTitleController
(
this
.
_onTapBack
,
this
.
_onTapMore
,
this
.
_onTapDownload
);
}
Flutter/superplayer_widget/lib/ui/superplayer_widget.dart
浏览文件 @
add7d5d1
...
...
@@ -33,6 +33,8 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
bool
_isShowControlView
=
false
;
bool
_isShowQualityListView
=
false
;
bool
_isShowDownload
=
false
;
bool
_isDownloaded
=
false
;
late
BottomViewController
_bottomViewController
;
late
QualityListViewController
_qualitListViewController
;
...
...
@@ -43,6 +45,7 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
StreamSubscription
?
_volumeSubscription
;
StreamSubscription
?
_pipSubscription
;
FTXDownloadListener
?
downloadListener
;
/// init
Timer
_controlViewTimer
=
Timer
(
const
Duration
(
milliseconds:
_controlViewShowTime
),
()
{});
...
...
@@ -66,8 +69,16 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
TXPipController
.
instance
.
exitAndReleaseCurrentPip
();
_playController
=
widget
.
_controller
;
_superPlayerFullUIController
=
SuperPlayerFullScreenController
(
_updateState
);
_titleViewController
=
_VideoTitleController
(
_onTapBack
,
()
{
_moreViewKey
.
currentState
?.
toggleShowMoreView
();
_titleViewController
=
_VideoTitleController
(
_onTapBack
,
// onTapMore
()
=>
_moreViewKey
.
currentState
?.
toggleShowMoreView
(),
// onTapDownload
()
{
if
(
_playController
.
videoModel
!=
null
)
{
_playController
.
startDownload
();
EasyLoading
.
showToast
(
"开始下载"
);
}
});
_bottomViewController
=
BottomViewController
(
_onTapPlayControl
,
_onControlFullScreen
,
_onControlQualityListView
,
(
value
)
{
...
...
@@ -164,14 +175,15 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
},
()
{
// onRcvFirstIframe
_coverViewKey
.
currentState
?.
hideCover
();
_refreshDownloadStatus
();
// 收到首帧事件后,先用播放器内核解析出来的分辨率对播放器大小进行调整
_calculateSize
(
_playController
.
videoWidth
,
_playController
.
videoHeight
);
},
()
{
// onPlayLoading
setState
(()
{
//预加载模式进行特殊处理
if
(
_playController
.
videoModel
!.
playAction
==
SuperPlayerModel
.
PLAY_ACTION_PRELOAD
)
{
if
(
_playController
.
callResume
)
{
if
(
_playController
.
videoModel
!.
playAction
==
SuperPlayerModel
.
PLAY_ACTION_PRELOAD
)
{
if
(
_playController
.
callResume
)
{
_isLoading
=
true
;
}
}
else
{
...
...
@@ -215,6 +227,9 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
{
return
SuperPlayerFullScreenView
(
_playController
,
_superPlayerFullUIController
);
}));
if
(
null
!=
downloadListener
)
{
DownloadHelper
.
instance
.
removeDownloadListener
(
downloadListener
!);
}
WidgetsBinding
.
instance
.
removeObserver
(
this
);
_playController
.
_updatePlayerUIStatus
(
SuperPlayerUIStatus
.
FULLSCREEN_MODE
);
_videoBottomKey
.
currentState
?.
updateUIStatus
(
SuperPlayerUIStatus
.
FULLSCREEN_MODE
);
...
...
@@ -229,6 +244,7 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
hideControlView
();
});
WidgetsBinding
.
instance
.
addObserver
(
this
);
_initDownloadStatus
();
}
void
_initPlayerState
()
{
...
...
@@ -260,6 +276,26 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
}
}
void
_initDownloadStatus
()
{
if
(
null
!=
downloadListener
)
{
DownloadHelper
.
instance
.
removeDownloadListener
(
downloadListener
!);
}
DownloadHelper
.
instance
.
addDownloadListener
(
downloadListener
=
FTXDownloadListener
((
event
,
info
)
{
if
(
event
==
TXVodPlayEvent
.
EVENT_DOWNLOAD_FINISH
)
{
EasyLoading
.
showToast
(
"视频下载完成"
);
}
_refreshDownloadStatus
();
},
(
errorCode
,
errorMsg
,
info
)
{
EasyLoading
.
showToast
(
"视频下载出错,code:
$errorCode
,msg:
$errorMsg
"
);
}));
if
(
null
!=
_playController
.
videoModel
)
{
// 仅支持点播视频下载
_isShowDownload
=
_playController
.
videoModel
!.
isEnableDownload
&&
_playController
.
playerType
==
SuperPlayerType
.
VOD
;
}
_refreshDownloadStatus
();
}
void
_updateState
()
{
// 刷新observer的绑定
_registerObserver
();
...
...
@@ -271,6 +307,10 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
}));
}
void
_refreshDownloadStatus
()
async
{
_isDownloaded
=
await
_playController
.
isDownloaded
();
}
@override
void
didChangeAppLifecycleState
(
AppLifecycleState
state
)
{
if
(
_isPlaying
&&
!
_isFloatingMode
)
{
...
...
@@ -401,7 +441,7 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
Widget
_getQualityListView
()
{
return
Visibility
(
visible:
_isShowQualityListView
,
child:
QualityListView
(
_qualitListViewController
,
_playController
.
currentQualiyList
,
child:
QualityListView
(
_qualitListViewController
,
_playController
.
currentQuali
t
yList
,
_playController
.
currentQuality
,
_qualityListKey
),
);
}
...
...
@@ -474,6 +514,8 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
_titleViewController
,
_playController
.
_playerUIStatus
==
SuperPlayerUIStatus
.
FULLSCREEN_MODE
,
_playController
.
_getPlayName
(),
_isShowDownload
,
_isDownloaded
,
_videoTitleKey
),
),
);
...
...
@@ -666,6 +708,9 @@ class SuperPlayerViewState extends State<SuperPlayerView> with WidgetsBindingObs
WidgetsBinding
.
instance
.
removeObserver
(
this
);
_pipSubscription
?.
cancel
();
_volumeSubscription
?.
cancel
();
if
(
null
!=
downloadListener
)
{
DownloadHelper
.
instance
.
removeDownloadListener
(
downloadListener
!);
}
super
.
dispose
();
}
}
...
...
Flutter/superplayer_widget/pubspec.yaml
浏览文件 @
add7d5d1
...
...
@@ -51,6 +51,9 @@ flutter:
-
images/superplayer_ic_vod_fullscreen.png
-
images/superplayer_top_shadow.png
-
images/superplayer_btn_back_play.png
-
images/superplayer_ic_vod_download.png
-
images/superplayer_ic_vod_check_done.png
-
images/superplayer_ic_vod_download_list.png
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论