ve_vod 1.48.20
ve_vod: ^1.48.20 copied to clipboard
This Flutter plugin provides vod player sdk native APIs for you to implement video play functions in your application
example/lib/main.dart
// ignore_for_file: prefer_const_constructors, unused_import
import 'dart:io';
import 'dart:ui';
import 'dart:convert';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:path_provider/path_provider.dart';
import 'package:ve_vod/ve_vod.dart';
import 'package:vod_player_flutter_example/component/generic_text_button_item.dart';
import 'package:vod_player_flutter_example/global_configuration.dart';
import 'package:vod_player_flutter_example/home/play_setting_page.dart';
import 'package:vod_player_flutter_example/platform_keys.dart';
import 'package:vod_player_flutter_example/short_video_play_scene.dart';
import 'package:vod_player_flutter_example/short_video/short_video_feed_item.dart';
import 'package:vod_player_flutter_example/short_video/short_video_feed_util.dart';
import 'package:vod_player_flutter_example/test_entry/test_entry.dart';
import 'package:vod_player_flutter_example/video_preload.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:vod_player_flutter_example/long_video/long_video_page.dart';
import 'package:vod_player_flutter_example/mini_drama/mini_drama_scene.dart';
import 'package:vod_player_flutter_example/utils/network_utils.dart';
void main() async {
if (Platform.isAndroid) {
WidgetsFlutterBinding.ensureInitialized();
}
runApp(const MyApp());
DartPluginRegistrant.ensureInitialized();
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<ShortVideoFeedItem>? shortVideofeedlist;
List<dynamic>? miniDramaEpisodes;
final String _appID = '229234';
@override
void initState() {
super.initState();
initPlatformState();
Connectivity()
.onConnectivityChanged
.listen((List<ConnectivityResult> result) async {
if (result.contains(ConnectivityResult.none)) {
Fluttertoast.showToast(
msg: "Network connection failed, please try again later",
gravity: ToastGravity.CENTER);
} else {
Fluttertoast.showToast(
msg: "Network restored, fetching feed again",
gravity: ToastGravity.CENTER);
// 确保配置已加载后再获取数据
await GlobalConfiguration.initSharedPreferences();
fetchShortVideoFeed();
fetchMiniDramaEpisodes();
}
// Received changes in available connectivity types!
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
await GlobalConfiguration.initSharedPreferences();
// Detect byteplus flag from compile-time environment variable
const String? byteplusEnable = String.fromEnvironment('BYTEPLUS_ENABLE');
if (byteplusEnable == 'true') {
GlobalConfiguration.isByteplusEnable = true;
}
// open log module
await FlutterTTSDKManager.openAllLog();
// regist log callback
TTFLogger.onLog = (logLevel, msg) {
print(msg);
};
// download
TTVideoEngineDownloadTaskManager.enableHlsProxy(true);
String docDir;
if (Platform.isIOS) {
docDir = (await getApplicationDocumentsDirectory()).path;
} else {
docDir = (await getDownloadsDirectory())!.path;
}
docDir = "$docDir/vevod_download";
TTVideoEngineDownloadTaskManager.setDownloadDirectory(docDir);
// setup
String licPath = 'assets/VEVod.license';
// please replace it with current channel, example "App Store" for iOS
String channel = Platform.isAndroid ? 'demo_channel_android' : 'App Store';
TTSDKVodConfiguration vodConfig = TTSDKVodConfiguration();
vodConfig.cacheMaxSize = 300 * 1024 * 1024;
TTSDKConfiguration sdkConfig =
TTSDKConfiguration.defaultConfigurationWithAppIDAndLicPath(
appID: _appID, licenseFilePath: licPath, channel: channel);
sdkConfig.vodConfiguration = vodConfig;
sdkConfig.appName = "bytevod_flutter_demo";
sdkConfig.appVersion = "1.1.1";
// sdkConfig.appRegion =
// TTSDKServiceVendor.TTSDKServiceVendorMYA; // 接入海外地域必填;不填写默认华北
await FlutterTTSDKManager.startWithConfiguration(sdkConfig);
// init startup auto select strategy
if (GlobalConfiguration.enableStartupAutoSelectBitrate) {
await FlutterTTSDKManager.initStartupAutoSelectStrategy();
}
// deviceID
FlutterTTSDKManager.setCurrentUserUniqueID('test_1234');
String? uniqueID = await FlutterTTSDKManager.getCurrentUserUniqueID();
String? deviceID = await FlutterTTSDKManager.getDeviceID();
String? engineUniqueId = await FlutterTTSDKManager.getEngineUniqueId();
print(
"TTF -- uniqueId:$uniqueID deviceId:$deviceID engineUniqueId:$engineUniqueId");
// strategy
updateStrategy();
// download
updateDownloader();
if (!mounted) return;
setState(() {});
}
Future<void> updateDownloader() async {
TTVideoEngineDownloadTaskManager.setMaxDownloadOperationCount(3); // 最大并发下载数
TTVideoEngineDownloadTaskManager.setLimitFreeDiskSize(
1024 * 1024 * 1024); // 空闲磁盘空间大小
TTVideoEngineDownloadTaskManager.setLimitFreeDiskCount(500); // 空闲磁盘空间文件数
TTVideoEngineDownloadTaskManager.loadAllTask();
}
Future<void> updateStrategy() async {
if (GlobalConfiguration.enableStrategyPreload &&
GlobalConfiguration.enableStrategyPreRender) {
TTVideoEngineStrategy.enableEngineStrategy(
strategyType: TTVideoEngineStrategyType.preloadAndPreRender,
scene: TTVideoEngineStrategyScene.smallVideo);
_enableEnginePreRenderStrategy(true);
} else if (GlobalConfiguration.enableStrategyPreload) {
TTVideoEngineStrategy.enableEngineStrategy(
strategyType: TTVideoEngineStrategyType.preload,
scene: TTVideoEngineStrategyScene.smallVideo);
} else if (GlobalConfiguration.enableStrategyPreRender) {
TTVideoEngineStrategy.enableEngineStrategy(
strategyType: TTVideoEngineStrategyType.preRender,
scene: TTVideoEngineStrategyScene.smallVideo);
_enableEnginePreRenderStrategy(true);
} else {
TTVideoEngineStrategy.clearAllEngineStrategy();
}
}
Future<void> fetchShortVideoFeed() async {
if (shortVideofeedlist != null) {
return;
}
ShortVideoFeedUtil.requestFeed((List<ShortVideoFeedItem>? feedlist) {
if (feedlist != null) {
setState(() {
shortVideofeedlist = feedlist;
Fluttertoast.showToast(
msg: "Fetched short-video data successfully",
gravity: ToastGravity.CENTER);
});
} else {
Fluttertoast.showToast(
msg: "Failed to fetch data, please exit and try again",
gravity: ToastGravity.CENTER);
}
});
}
Future<void> fetchMiniDramaEpisodes() async {
if (miniDramaEpisodes != null) {
return;
}
final bool useVidSource = GlobalConfiguration.miniDramaVideoSourceType == 0;
final String apiUrl = useVidSource
? 'https://vevod-demo-server.volcvod.com/api/drama/episode/v1/getEpisodeFeedStreamWithPlayAuthToken'
: 'https://vevod-demo-server.volcvod.com/api/drama/episode/v1/getDramaEpisodeWithVideoModel';
final episodes = await NetworkUtils.postRequestForResult(
apiUrl,
{
'authorId': 'mini-drama-video',
'needSsl': true,
'dramaId': '3',
'offset': 0,
'pageSize': 50,
'format': GlobalConfiguration.miniDramaVideoFormat,
},
errorMessage: 'Failed to fetch mini drama data',
);
if (episodes != null) {
Fluttertoast.showToast(
msg: "Fetched mini drama data successfully",
gravity: ToastGravity.CENTER);
setState(() {
miniDramaEpisodes = episodes;
});
}
}
Future<void> _enableEnginePreRenderStrategy(bool enable) async {
if (enable) {
TTVideoEngineStrategy.init();
TTVideoEngineStrategy.onCreatePreRenderEngine = ((source) async {
VodPlayerFlutter player = VodPlayerFlutter();
String coreHashHex =
await player.createPlayer(vid: source.getVid, preCreated: true);
player.setMediaSource(source);
player.setHardwareDecode(GlobalConfiguration.isHardwareDecode);
player.setTrackVolumeEnabled(GlobalConfiguration.isTrackVolume);
player.setScalingMode(
TTVideoEngineScalingMode.TTVideoEngineScalingModeAspectFit);
player.openTextureRender(!GlobalConfiguration.closeTextureRender);
player.setLooping(true);
player.setCustomHeader('x-tt-flutter-test-demo', '1');
print(
'TTF -- TTVideoEngineStrategyPreRender onCreatePreRenderEngine, hashCode:${player.hashCode} engine:$coreHashHex vid:${source.getVid}');
return player;
});
TTVideoEngineStrategy.onPlayerCreated = ((player) {
if (player != null) {
print('TTF ---o onPlayerCreated, hashCode ' +
player.hashCode.toString());
}
});
print('TTF -- TTVideoEngineStrategyPreRender - init end');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Builder(
builder: (context) => Scaffold(
backgroundColor: const Color.fromRGBO(244, 245, 247, 1),
body: ListView(
padding: EdgeInsets.zero,
children: [
Container(
height: 280,
color: Colors.transparent,
child: Stack(
children: [
Image.asset(
'assets/images/icon_home_background.png',
),
const Positioned(
top: 180,
left: 30,
child: Text('Video on Demand',
style: TextStyle(
color: Colors.black,
fontSize: 24,
fontWeight: FontWeight.bold)),
),
const Positioned(
top: 220,
left: 30,
child: Text('Experience an all-in-one video solution',
style: TextStyle(color: Colors.black, fontSize: 16)),
),
],
),
),
GenericTextButtonItem(
iconAssetPath: 'assets/images/icon_short.png',
buttonText: 'Short Video (Vertical)',
onPressed: () {
if (shortVideofeedlist == null) {
Fluttertoast.showToast(
msg: "No data yet, please try again later");
} else {
if (_appID.isEmpty) {
Fluttertoast.showToast(
msg:
"Please contact Volcano Engine Business to get the demo AppId and License.",
gravity: ToastGravity.CENTER);
return;
}
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ShortVideoScene(
feedlist: shortVideofeedlist!,
),
),
);
}
}),
SizedBox(height: 10),
GenericTextButtonItem(
iconAssetPath: 'assets/images/icon_short.png',
buttonText: 'Mini Drama',
onPressed: () {
if (miniDramaEpisodes == null) {
Fluttertoast.showToast(
msg: 'No data yet, please try again later',
gravity: ToastGravity.CENTER);
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MiniDramaScene(
initialEpisodesJson: miniDramaEpisodes,
),
),
);
}
}),
SizedBox(height: 10),
GenericTextButtonItem(
iconAssetPath: 'assets/images/icon_test.png',
buttonText: 'Long Video',
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LongVideoPage(),
),
);
}),
SizedBox(height: 10),
GenericTextButtonItem(
iconAssetPath: 'assets/images/icon_test.png',
buttonText: 'Test',
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const TestPage(),
),
);
}),
SizedBox(height: 10),
GenericTextButtonItem(
iconAssetPath: 'assets/images/icon_setting.png',
buttonText: 'Playback Settings',
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const PlaySettingPage(),
),
);
}),
SizedBox(height: 20),
Container(
height: 75,
margin: const EdgeInsets.symmetric(horizontal: 10),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Text(
've_vod version: ${FlutterTTSDKManager.TTSDK_FLUTTER_VERSION}',
style: TextStyle(
color: Color.fromRGBO(170, 170, 170, 1),
fontSize: 14,
fontWeight: FontWeight.w300)),
Text('Beijing Volcano Engine Technology Co.,Ltd.',
style: TextStyle(
color: Color.fromRGBO(170, 170, 170, 1),
fontSize: 14,
fontWeight: FontWeight.w300)),
],
),
)
],
),
),
));
}
}