提交 75524b84 authored 作者: kongdywang's avatar kongdywang

fix video download delete error on url & update docs

上级 0a65ab8a
...@@ -5,7 +5,9 @@ package com.tencent.vod.flutter; ...@@ -5,7 +5,9 @@ package com.tencent.vod.flutter;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.tencent.rtmp.downloader.ITXVodDownloadListener; import com.tencent.rtmp.downloader.ITXVodDownloadListener;
import com.tencent.rtmp.downloader.ITXVodPreloadListener; import com.tencent.rtmp.downloader.ITXVodPreloadListener;
import com.tencent.rtmp.downloader.TXVodDownloadDataSource; import com.tencent.rtmp.downloader.TXVodDownloadDataSource;
...@@ -23,6 +25,7 @@ import com.tencent.vod.flutter.tools.CommonUtil; ...@@ -23,6 +25,7 @@ import com.tencent.vod.flutter.tools.CommonUtil;
import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.EventChannel;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -117,7 +120,7 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown ...@@ -117,7 +120,7 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
msg.setQuality((long) dataSource.getQuality()); msg.setQuality((long) dataSource.getQuality());
msg.setToken(dataSource.getToken()); msg.setToken(dataSource.getToken());
} }
msg.setSpeed((long)mediaInfo.getSpeed()); msg.setSpeed((long) mediaInfo.getSpeed());
msg.setIsResourceBroken(mediaInfo.isResourceBroken()); msg.setIsResourceBroken(mediaInfo.isResourceBroken());
} }
return msg; return msg;
...@@ -160,7 +163,7 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown ...@@ -160,7 +163,7 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
} }
private TXVodDownloadMediaInfo parseMediaInfoFromInfo(Integer quality, String url, Integer appId, private TXVodDownloadMediaInfo parseMediaInfoFromInfo(Integer quality, String url, Integer appId,
String fileId, String userName) { String fileId, String userName) {
TXVodDownloadMediaInfo mediaInfo = null; TXVodDownloadMediaInfo mediaInfo = null;
if (null == userName) { if (null == userName) {
userName = "default"; userName = "default";
...@@ -169,11 +172,40 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown ...@@ -169,11 +172,40 @@ public class FTXDownloadManager implements ITXVodDownloadListener, TXFlutterDown
mediaInfo = TXVodDownloadManager.getInstance() mediaInfo = TXVodDownloadManager.getInstance()
.getDownloadMediaInfo(appId, fileId, optQuality(quality), userName); .getDownloadMediaInfo(appId, fileId, optQuality(quality), userName);
} else if (!TextUtils.isEmpty(url)) { } else if (!TextUtils.isEmpty(url)) {
mediaInfo = TXVodDownloadManager.getInstance().getDownloadMediaInfo(url); mediaInfo = TXVodDownloadManager.getInstance().getDownloadMediaInfo(url, -1L, userName);
// To prevent the issue where downloading from the URL does not support specifying the userName
if (null == mediaInfo) {
mediaInfo = parseMediaInfoFromInfoByAll(quality, url, appId, fileId, userName);
}
} }
return mediaInfo; return mediaInfo;
} }
private TXVodDownloadMediaInfo parseMediaInfoFromInfoByAll(Integer quality, String url, Integer appId,
String fileId, String userName) {
boolean isFileIdInfo = null != appId && null != fileId;
boolean isUrlInfo = !TextUtils.isEmpty(url);
List<TXVodDownloadMediaInfo> mediaInfoList = TXVodDownloadManager.getInstance().getDownloadMediaInfoList();
if (null != mediaInfoList && (isFileIdInfo || isUrlInfo)) {
for (TXVodDownloadMediaInfo mediaInfo : mediaInfoList) {
if (TextUtils.equals(userName, mediaInfo.getUserName())) {
if (isFileIdInfo) {
TXVodDownloadDataSource dataSource = mediaInfo.getDataSource();
if (null != dataSource) {
if (dataSource.getAppId() == appId && TextUtils.equals(dataSource.getFileId(), fileId)
&& optQuality(quality) == dataSource.getQuality()) {
return mediaInfo;
}
}
} else if (TextUtils.equals(url, mediaInfo.getUrl())) {
return mediaInfo;
}
}
}
}
return null;
}
private int optQuality(Integer quality) { private int optQuality(Integer quality) {
return quality == null ? TXVodDownloadDataSource.QUALITY_UNK : quality; return quality == null ? TXVodDownloadDataSource.QUALITY_UNK : quality;
} }
......
...@@ -1171,7 +1171,72 @@ Future<int> enterPictureInPictureMode({String? backIconForAndroid, String? playI ...@@ -1171,7 +1171,72 @@ Future<int> enterPictureInPictureMode({String? backIconForAndroid, String? playI
| ERROR_IOS_PIP_IS_RUNNING | -110 | PIP功能已经运行,只适用于 iOS | ERROR_IOS_PIP_IS_RUNNING | -110 | PIP功能已经运行,只适用于 iOS
| ERROR_IOS_PIP_NOT_RUNNING | -111 | PIP功能没有启动,只适用于 iOS | ERROR_IOS_PIP_NOT_RUNNING | -111 | PIP功能没有启动,只适用于 iOS
### initImageSprite
**说明**
初始化视频雪碧图
**接口**
```dart
Future<void> initImageSprite(String? vvtUrl, List<String>? imageUrls) async;
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| vvtUrl | String | 雪碧图 web vtt 描述文件下载 URL |
| imageUrls | List<String> | 雪碧图图片下载 URL |
**返回值说明**
### getImageSprite
**说明**
获取加载的雪碧图
**接口**
```dart
Future<Uint8List?> getImageSprite(double time) async;
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| time | double | 时间点,单位秒 |
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| thumb | Uint8List | 雪碧图 |
### exitPictureInPictureMode
**说明**
退出画中画,如果该播放器处于画中画模式
**接口**
```dart
Future<void> exitPictureInPictureMode() async;
```
**参数说明**
**返回值说明**
## FTXVodPlayConfig类 ## FTXVodPlayConfig类
...@@ -1324,29 +1389,6 @@ Future<bool> stop({bool isNeedClear = false}) async; ...@@ -1324,29 +1389,6 @@ Future<bool> stop({bool isNeedClear = false}) async;
| result | bool | 停止是否成功 | | result | bool | 停止是否成功 |
### setIsAutoPlay
**说明**
设置即将播放的视频,在startVodPlay加载视频地址之后,是否直接自动播放
**接口**
```dart
Future<void> setIsAutoPlay({bool? isAutoPlay}) async;
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| isAutoPlay | bool | 是否自动播放 |
**返回值说明**
### isPlaying ### isPlaying
**说明** **说明**
...@@ -1462,29 +1504,6 @@ Future<void> setAppID(int appId) async; ...@@ -1462,29 +1504,6 @@ Future<void> setAppID(int appId) async;
### resumeLive
**说明**
停止时移播放,返回直播
**接口**
```dart
Future<int> resumeLive() async;
```
**参数说明**
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| result | int | 1 成功, 0 失败 |
### setConfig ### setConfig
**说明** **说明**
...@@ -1899,30 +1918,6 @@ Future<bool> deleteDownloadMediaInfo(TXVodDownloadMediaInfo mediaInfo) async ...@@ -1899,30 +1918,6 @@ Future<bool> deleteDownloadMediaInfo(TXVodDownloadMediaInfo mediaInfo) async
| result | bool | 删除结果| | result | bool | 删除结果|
### deleteDownloadMediaInfo
**说明**
删除下载的视频
**接口**
```dart
Future<bool> deleteDownloadMediaInfo(TXVodDownloadMediaInfo mediaInfo) async
```
**参数说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| mediaInfo | TXVodDownloadMediaInfo | 任务下载信息|
**返回值说明**
| 参数名 | 类型 | 描述 |
| ------ | ------ | ------------------ |
| result | bool | 删除结果|
......
...@@ -48,15 +48,20 @@ Flutter播放器组件是基于flutter播放器SDK的扩展,播放器组件对 ...@@ -48,15 +48,20 @@ Flutter播放器组件是基于flutter播放器SDK的扩展,播放器组件对
superplayer_widget: superplayer_widget:
# 该路径根据superplayer_widget存放路径改变 # 该路径根据superplayer_widget存放路径改变
path: ../superplayer_widget path: ../superplayer_widget
super_player:
git:
url: https://github.com/LiteAVSDK/Player_Flutter
path: Flutter
ref: main
``` ```
** ref 可以根据自身项目需要,替换为对应的版本或分支。 **
3. 修改superplayer_widget的`superPlayer`依赖 3. 修改superplayer_widget的`superPlayer`依赖
进入修改superplayer_widget的`pubspec.yaml` 进入修改superplayer_widget的`pubspec.yaml`
将如下配置进行替换 将如下配置进行替换
```yaml ```yaml
super_player: super_player:
path: ../ path: ../
``` ```
替换为 替换为
...@@ -738,7 +743,7 @@ DownloadHelper.instance.removeDownloadListener(listener); ...@@ -738,7 +743,7 @@ DownloadHelper.instance.removeDownloadListener(listener);
此外,还可以通过`TXVodDownloadController.instance.getDownloadInfo(mediaInfo)`方法或者`TXVodDownloadController.instance.getDownloadList()`方法直接查询mediaInfo中的downloadState来判断下载状态。 此外,还可以通过`TXVodDownloadController.instance.getDownloadInfo(mediaInfo)`方法或者`TXVodDownloadController.instance.getDownloadList()`方法直接查询mediaInfo中的downloadState来判断下载状态。
#### 5、播放下载视频 #### 5、播放下载视频
`TXVodDownloadController.instance.getDownloadInfo(mediaInfo)``TXVodDownloadController.instance.getDownloadList()`获得到的视频信息中有个playPath字段,使用TXVodPlayerController直接播放即可 `TXVodDownloadController.instance.getDownloadInfo(mediaInfo)``TXVodDownloadController.instance.getDownloadList()`获得到的视频信息中有个playPath字段,使用TXVodPlayerController直接播放即可
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
本文档部分内容为腾讯云专属能力,使用前请开通 [腾讯云](https://cloud.tencent.com/) 相关服务,未注册用户可注册账号 [免费试用](https://cloud.tencent.com/login) 本文档部分内容为腾讯云专属能力,使用前请开通 [腾讯云](https://cloud.tencent.com/) 相关服务,未注册用户可注册账号 [免费试用](https://cloud.tencent.com/login)
## 通过本文你可以学会 ## 通过本文你可以学会
* 如何集成腾讯云视立方 Flutter 播放器SDK * 如何集成腾讯云 Flutter 播放器SDK
* 如何使用播放器 SDK 进行点播播放 * 如何使用播放器 SDK 进行点播播放
* 如何使用播放器 SDK 底层能力实现更多功能 * 如何使用播放器 SDK 底层能力实现更多功能
......
...@@ -138,30 +138,6 @@ _controller.switchStream("http://5815.liveplay.myqcloud.com/live/5815_62fe94d692 ...@@ -138,30 +138,6 @@ _controller.switchStream("http://5815.liveplay.myqcloud.com/live/5815_62fe94d692
> You need to configure PTS alignment on the backend to use the seamless video quality change feature. To do this, please [submit a ticket](https://console.cloud.tencent.com/workorder). > You need to configure PTS alignment on the backend to use the seamless video quality change feature. To do this, please [submit a ticket](https://console.cloud.tencent.com/workorder).
### Step 8. Replay a live stream
The time shifting feature allows you to return to any previous time point during a live stream and resume playback from that time point. It is highly suitable for scenarios in which there is no need for interaction but viewers may want to rewind and replay a video, such as sports and gaming events.
```dart
// Call `startLivePlay` first before setting time shifting
// Start playback
await _controller.setAppID(appId); // Configure `appId`
await _controller.prepareLiveSeek(domian, bizidNum); // The backend requests the live streaming start time
```
After correct configuration, the current progress will not start from 0 in the `LAY_EVT_PLAY_PROGRESS` event, but will be calculated based on the actual playback start time.
Call the `seek` method to start live streaming again from a previous time point
```dart
await _controller.seek(600); // Start playback from the 10th minute
```
Configure the following settings on the backend to connect to time shifting:
1. Recording: Configure the time shifting duration and time shifting storage period.
2. Playback: Enable metadata acquisition in time shifting.
The time shifting feature is currently in beta testing. To use it, please submit a ticket.
<h2 id="Delay">Latency Adjustment</h2> <h2 id="Delay">Latency Adjustment</h2>
The live playback feature of the SDK is not based on FFmpeg, but Tencent Cloud's proprietary playback engine, which is why the SDK offers better latency control than open-source players do. We provide three latency control modes, which can be used for showrooms, game streaming, and hybrid scenarios. The live playback feature of the SDK is not based on FFmpeg, but Tencent Cloud's proprietary playback engine, which is why the SDK offers better latency control than open-source players do. We provide three latency control modes, which can be used for showrooms, game streaming, and hybrid scenarios.
......
...@@ -117,30 +117,6 @@ _controller.switchStream("http://5815.liveplay.myqcloud.com/live/5815_62fe94d692 ...@@ -117,30 +117,6 @@ _controller.switchStream("http://5815.liveplay.myqcloud.com/live/5815_62fe94d692
>清晰度无缝切换功能需要在后台配置 PTS 对齐,如您需要可 [提交工单](https://console.cloud.tencent.com/workorder) 申请使用。 >清晰度无缝切换功能需要在后台配置 PTS 对齐,如您需要可 [提交工单](https://console.cloud.tencent.com/workorder) 申请使用。
### step 7: 直播回看
时移功能是腾讯云推出的特色能力,可以在直播过程中,随时观看回退到任意直播历史时间点,并能在此时间点一直观看直播。非常适合游戏、球赛等互动性不高,但观看连续性较强的场景。
```dart
// 设置直播回看前,先调用 startLivePlay
// 开始播放 ...
await _controller.setAppID(appId); // 配置 appId
await _controller.prepareLiveSeek(domian, bizidNum); // 后台请求直播起始时间
```
配置正确后,在 PLAY_EVT_PLAY_PROGRESS 事件里,当前进度就不是从0开始,而是根据实际开播时间计算而来。
调用 seek 方法,就能从历史事件点重新直播
```dart
await _controller.seek(600); // 从第10分钟开始播放
```
接入时移需要在后台打开2处配置:
1. 录制:配置时移时长、时移储存时长
2. 播放:时移获取元数据
时移功能处于公测申请阶段,如您需要可提交工单申请使用。
<h2 id="Delay">延时调节</h2> <h2 id="Delay">延时调节</h2>
腾讯云 SDK 的直播播放(LVB)功能,并非基于 ffmpeg 做二次开发, 而是采用了自研的播放引擎,所以相比于开源播放器,在直播的延迟控制方面有更好的表现,我们提供了三种延迟调节模式,分别适用于:秀场,游戏以及混合场景。 腾讯云 SDK 的直播播放(LVB)功能,并非基于 ffmpeg 做二次开发, 而是采用了自研的播放引擎,所以相比于开源播放器,在直播的延迟控制方面有更好的表现,我们提供了三种延迟调节模式,分别适用于:秀场,游戏以及混合场景。
......
...@@ -76,8 +76,29 @@ flutter pub upgrade ...@@ -76,8 +76,29 @@ flutter pub upgrade
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
``` ```
** 网络安全配置允许 App 发送 http 请求 **
出于安全考虑,从 Android P 开始,Google 要求 App 的请求都使用加密链接。播放器 SDK 会启动一个 localsever 代理 http 请求,如果您的应用 **targetSdkVersion 大于或等于28**,可以通过 [网络安全配置](https://developer.android.com/training/articles/security-config?hl=zh-cn) 来开启允许向127.0.0.1发送 http 请求。 否则播放时将出现 "java.io.IOException: Cleartext HTTP traffic to 127.0.0.1 not permitted" 错误, 导致无法播放视频。配置步骤如下:
2.1. 在项目新建 res/xml/network_security_config.xml 文件,设置网络安全性配置。
```xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">127.0.0.1</domain>
</domain-config>
</network-security-config>
```
2.2. 在 AndroidManifest.xml 文件下的 application 标签增加以下属性。
```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
```
2. 确保 Android 目录下的 `build.gradle` 使用了mavenCenter,能够成功下载到依赖 3. 确保 Android 目录下的 `build.gradle` 使用了mavenCenter,能够成功下载到依赖
```groovy ```groovy
repositories { repositories {
...@@ -85,7 +106,7 @@ repositories { ...@@ -85,7 +106,7 @@ repositories {
} }
``` ```
3. 配置安卓最小SDK版本,由于flutter默认配置的安卓最小版本过低,需要手动更改为至少19,如果需要使用画中画能力,compileSdkVersion和targetSdkVersion则需要修改为至少31 4. 配置安卓最小SDK版本,由于flutter默认配置的安卓最小版本过低,需要手动更改为至少19,如果需要使用画中画能力,compileSdkVersion和targetSdkVersion则需要修改为至少31
```groovy ```groovy
compileSdkVersion 31 compileSdkVersion 31
...@@ -98,7 +119,7 @@ defaultConfig { ...@@ -98,7 +119,7 @@ defaultConfig {
} }
``` ```
4. `AndroidManifest.xml`根节点manifest标签内增加如下配置`xmlns:tools="http://schemas.android.com/tools"`,示例如下: 5. `AndroidManifest.xml`根节点manifest标签内增加如下配置`xmlns:tools="http://schemas.android.com/tools"`,示例如下:
```xml ```xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
...@@ -120,7 +141,7 @@ application节点下增加`tools:replace="android:label"`,示例如下 ...@@ -120,7 +141,7 @@ application节点下增加`tools:replace="android:label"`,示例如下
</application> </application>
``` ```
5. 如果需要更新原生SDK依赖版本,可手动删除 Android 目录下的 `build` 文件夹,也可以使用如下命令强制刷新 6. 如果需要更新原生SDK依赖版本,可手动删除 Android 目录下的 `build` 文件夹,也可以使用如下命令强制刷新
```shell ```shell
./gradlew build ./gradlew build
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论