From 143b6322e2bdadf7dc7b36426f2d62fc25ce309a Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Tue, 4 Jun 2024 10:40:31 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E9=80=80=E5=87=BA=E5=B0=8F=E7=AA=97?= =?UTF-8?q?=E6=97=B6=E6=81=A2=E5=A4=8D=E5=8E=9F=E5=A7=8B=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live_room/player/player_controller.dart | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/simple_live_app/lib/modules/live_room/player/player_controller.dart b/simple_live_app/lib/modules/live_room/player/player_controller.dart index 63b48fb..107ac03 100644 --- a/simple_live_app/lib/modules/live_room/player/player_controller.dart +++ b/simple_live_app/lib/modules/live_room/player/player_controller.dart @@ -282,11 +282,19 @@ mixin PlayerSystemMixin on PlayerMixin, PlayerStateMixin, PlayerDanmakuMixin { //danmakuController?.clear(); } + Size? _lastWindowSize; + Offset? _lastWindowPosition; + ///小窗模式() - void enterSmallWindow() { + void enterSmallWindow() async { if (!(Platform.isAndroid || Platform.isIOS)) { fullScreenState.value = true; smallWindowState.value = true; + + // 读取窗口大小 + _lastWindowSize = await windowManager.getSize(); + _lastWindowPosition = await windowManager.getPosition(); + windowManager.setTitleBarStyle(TitleBarStyle.hidden); // 获取视频窗口大小 var width = player.state.width ?? 16; @@ -311,9 +319,10 @@ mixin PlayerSystemMixin on PlayerMixin, PlayerStateMixin, PlayerDanmakuMixin { fullScreenState.value = false; smallWindowState.value = false; windowManager.setTitleBarStyle(TitleBarStyle.normal); - windowManager.setSize(const Size(1280, 720)); + windowManager.setSize(_lastWindowSize!); + windowManager.setPosition(_lastWindowPosition!); windowManager.setAlwaysOnTop(false); - windowManager.setAlignment(Alignment.center); + //windowManager.setAlignment(Alignment.center); } } From ce9bac6e40ef4334dbc50536d302e0cd0af19060 Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Tue, 4 Jun 2024 18:00:37 +0800 Subject: [PATCH 02/13] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=A0=B9=E6=8D=AE?= =?UTF-8?q?=E4=BC=A0=E6=84=9F=E5=99=A8=E8=8E=B7=E5=8F=96=E6=96=B9=E5=90=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/modules/user/test_page.dart | 83 +++++++++++++++++++ .../lib/modules/user/user_page.dart | 11 +++ simple_live_app/lib/routes/app_pages.dart | 10 +++ simple_live_app/lib/routes/route_path.dart | 3 + simple_live_app/pubspec.yaml | 1 + 5 files changed, 108 insertions(+) create mode 100644 simple_live_app/lib/modules/user/test_page.dart diff --git a/simple_live_app/lib/modules/user/test_page.dart b/simple_live_app/lib/modules/user/test_page.dart new file mode 100644 index 0000000..a988687 --- /dev/null +++ b/simple_live_app/lib/modules/user/test_page.dart @@ -0,0 +1,83 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:sensors_plus/sensors_plus.dart'; +import 'package:simple_live_app/app/log.dart'; + +class TestPage extends GetView { + const TestPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + body: Center( + child: Obx( + () => Text( + controller.orientation.value, + style: const TextStyle(fontSize: 32, color: Colors.white), + ), + ), + ), + ); + } +} + +class TestController extends GetxController { + var orientation = "".obs; + + @override + void onInit() { + setLandscape(); + super.onInit(); + } + + void setLandscape() async { + await SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeLeft, + ]); + orientation.value = "LANDSCAPE LEFT"; + listenSensor(); + } + + StreamSubscription? _streamSubscription; + + void listenSensor() { + // 监听传感器事件,获取当前设备的方向 + _streamSubscription = accelerometerEventStream( + samplingPeriod: const Duration(seconds: 1), + ).listen((AccelerometerEvent event) { + var x = event.x; + var y = event.y; + + var newOrientation = ""; + if (x >= 9.0 && y < 9.0 && y >= -9.0) { + newOrientation = "LANDSCAPE LEFT"; + } else if (x <= -9.0 && y < 9.0 && y >= -9.0) { + newOrientation = "LANDSCAPE RIGHT"; + } + if (orientation.value != newOrientation && newOrientation.isNotEmpty) { + orientation.value = newOrientation; + if (orientation.value == "LANDSCAPE RIGHT") { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeRight, + ]); + } else { + SystemChrome.setPreferredOrientations([ + DeviceOrientation.landscapeLeft, + ]); + } + Log.d("newOrientation: $newOrientation"); + } + }); + } + + @override + void onClose() { + SystemChrome.setPreferredOrientations(DeviceOrientation.values); + _streamSubscription?.cancel(); + super.onClose(); + } +} diff --git a/simple_live_app/lib/modules/user/user_page.dart b/simple_live_app/lib/modules/user/user_page.dart index 9d8ef33..42a6601 100644 --- a/simple_live_app/lib/modules/user/user_page.dart +++ b/simple_live_app/lib/modules/user/user_page.dart @@ -193,6 +193,17 @@ class UserPage extends StatelessWidget { Get.toNamed(RoutePath.kSettingsOther); }, ), + ListTile( + leading: const Icon(Remix.apps_line), + title: const Text("测试"), + trailing: const Icon( + Icons.chevron_right, + color: Colors.grey, + ), + onTap: () { + Get.toNamed(RoutePath.kTest); + }, + ), ], ), Divider( diff --git a/simple_live_app/lib/routes/app_pages.dart b/simple_live_app/lib/routes/app_pages.dart index 665df83..f187e5c 100644 --- a/simple_live_app/lib/routes/app_pages.dart +++ b/simple_live_app/lib/routes/app_pages.dart @@ -36,6 +36,7 @@ import 'package:simple_live_app/modules/user/indexed_settings/indexed_settings_p import 'package:simple_live_app/modules/user/other/other_settings_controller.dart'; import 'package:simple_live_app/modules/user/other/other_settings_page.dart'; import 'package:simple_live_app/modules/user/play_settings_page.dart'; +import 'package:simple_live_app/modules/user/test_page.dart'; import '../modules/indexed/indexed_page.dart'; import 'route_path.dart'; @@ -202,5 +203,14 @@ class AppPages { BindingsBuilder.put(() => OtherSettingsController()), ], ), + + //测试页面 + GetPage( + name: RoutePath.kTest, + page: () => const TestPage(), + bindings: [ + BindingsBuilder.put(() => TestController()), + ], + ), ]; } diff --git a/simple_live_app/lib/routes/route_path.dart b/simple_live_app/lib/routes/route_path.dart index 5a06d95..a961e05 100644 --- a/simple_live_app/lib/routes/route_path.dart +++ b/simple_live_app/lib/routes/route_path.dart @@ -62,4 +62,7 @@ class RoutePath { /// 同步设备 static const kSyncDevice = "/sync/device"; + + /// 测试页面 + static const kTest = "/test"; } diff --git a/simple_live_app/pubspec.yaml b/simple_live_app/pubspec.yaml index ee44d34..91cb39e 100644 --- a/simple_live_app/pubspec.yaml +++ b/simple_live_app/pubspec.yaml @@ -57,6 +57,7 @@ dependencies: flutter_inappwebview: ^5.8.0 #WebView connectivity_plus: ^6.0.3 #网络状态 qr_code_scanner: ^1.0.1 #二维码扫描 + sensors_plus: ^5.0.1 #传感器 # 网络相关 shelf: ^1.4.1 From 5bb10d2b314717ac0c60e870fc7b6a18f95c2fb5 Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Thu, 6 Jun 2024 08:30:44 +0800 Subject: [PATCH 03/13] =?UTF-8?q?=E6=B5=8B=E8=AF=95motion=5Fsensors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/modules/user/test_page.dart | 36 ++++++++++++++++--- simple_live_app/pubspec.yaml | 4 +++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/simple_live_app/lib/modules/user/test_page.dart b/simple_live_app/lib/modules/user/test_page.dart index a988687..7a9b286 100644 --- a/simple_live_app/lib/modules/user/test_page.dart +++ b/simple_live_app/lib/modules/user/test_page.dart @@ -5,6 +5,7 @@ import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:sensors_plus/sensors_plus.dart'; import 'package:simple_live_app/app/log.dart'; +import 'package:motion_sensors/motion_sensors.dart' as motion_sensors; class TestPage extends GetView { const TestPage({super.key}); @@ -43,12 +44,38 @@ class TestController extends GetxController { } StreamSubscription? _streamSubscription; - + StreamSubscription? _orientationStreamSubscription; void listenSensor() { // 监听传感器事件,获取当前设备的方向 - _streamSubscription = accelerometerEventStream( - samplingPeriod: const Duration(seconds: 1), - ).listen((AccelerometerEvent event) { + // _streamSubscription = accelerometerEventStream( + // samplingPeriod: const Duration(seconds: 1), + // ).listen((AccelerometerEvent event) { + // var x = event.x; + // var y = event.y; + + // var newOrientation = ""; + // if (x >= 9.0 && y < 9.0 && y >= -9.0) { + // newOrientation = "LANDSCAPE LEFT"; + // } else if (x <= -9.0 && y < 9.0 && y >= -9.0) { + // newOrientation = "LANDSCAPE RIGHT"; + // } + // if (orientation.value != newOrientation && newOrientation.isNotEmpty) { + // orientation.value = newOrientation; + // if (orientation.value == "LANDSCAPE RIGHT") { + // SystemChrome.setPreferredOrientations([ + // DeviceOrientation.landscapeRight, + // ]); + // } else { + // SystemChrome.setPreferredOrientations([ + // DeviceOrientation.landscapeLeft, + // ]); + // } + // Log.d("newOrientation: $newOrientation"); + // } + // }); + + _orientationStreamSubscription = + motion_sensors.motionSensors.accelerometer.listen((event) { var x = event.x; var y = event.y; @@ -78,6 +105,7 @@ class TestController extends GetxController { void onClose() { SystemChrome.setPreferredOrientations(DeviceOrientation.values); _streamSubscription?.cancel(); + _orientationStreamSubscription?.cancel(); super.onClose(); } } diff --git a/simple_live_app/pubspec.yaml b/simple_live_app/pubspec.yaml index 91cb39e..aa422ae 100644 --- a/simple_live_app/pubspec.yaml +++ b/simple_live_app/pubspec.yaml @@ -58,6 +58,10 @@ dependencies: connectivity_plus: ^6.0.3 #网络状态 qr_code_scanner: ^1.0.1 #二维码扫描 sensors_plus: ^5.0.1 #传感器 + motion_sensors: + git: + url: https://github.com/zesage/motion_sensors.git + ref: master # 网络相关 shelf: ^1.4.1 From d552a932300dd42e155904831241e1b4514d2489 Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Thu, 6 Jun 2024 17:00:15 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8A=96=E9=9F=B3?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98=20#431?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../live_room/live_room_controller.dart | 4 +- .../example/simple_live_core_example.dart | 14 +- simple_live_core/lib/src/douyin_site.dart | 236 ++++++++++++++---- 3 files changed, 203 insertions(+), 51 deletions(-) diff --git a/simple_live_app/lib/modules/live_room/live_room_controller.dart b/simple_live_app/lib/modules/live_room/live_room_controller.dart index ea7e662..e7e8511 100644 --- a/simple_live_app/lib/modules/live_room/live_room_controller.dart +++ b/simple_live_app/lib/modules/live_room/live_room_controller.dart @@ -281,7 +281,9 @@ class LiveRoomController extends PlayerController with WidgetsBindingObserver { detail.value = await site.liveSite.getRoomDetail(roomId: roomId); if (site.id == Constant.kDouyin) { - // 如果是抖音,且收藏的是Rid,需要转换roomID + // 1.6.0之前收藏的WebRid + // 1.6.0收藏的RoomID + // 1.6.0之后改回WebRid if (detail.value!.roomId != roomId) { var oldId = roomId; rxRoomId.value = detail.value!.roomId; diff --git a/simple_live_core/example/simple_live_core_example.dart b/simple_live_core/example/simple_live_core_example.dart index 626809f..45212ec 100644 --- a/simple_live_core/example/simple_live_core_example.dart +++ b/simple_live_core/example/simple_live_core_example.dart @@ -20,13 +20,13 @@ void main() async { }; //var categores = await site.getCategores(); //print(categores.length); - var detail = await site.getRoomDetail(roomId: "7375009979071236915"); - // var playQualites = await site.getPlayQualites(detail: detail); - // var playUrls = - // await site.getPlayUrls(detail: detail, quality: playQualites.first); - // for (var element in playUrls) { - // print(element); - // } + var detail = await site.getRoomDetail(roomId: "7376294819431238409"); + var playQualites = await site.getPlayQualites(detail: detail); + var playUrls = + await site.getPlayUrls(detail: detail, quality: playQualites.first); + for (var element in playUrls) { + print(element); + } //print(detail); danmaku.start(detail.danmakuData); diff --git a/simple_live_core/lib/src/douyin_site.dart b/simple_live_core/lib/src/douyin_site.dart index 8097916..336ec20 100644 --- a/simple_live_core/lib/src/douyin_site.dart +++ b/simple_live_core/lib/src/douyin_site.dart @@ -174,32 +174,53 @@ class DouyinSite implements LiveSite { @override Future getRoomDetail({required String roomId}) async { - // 检查roomId是否为webRid - if (roomId.length < 15) { - return await getRoomDetailByWebRid(roomId); + // 有两种roomId,一种是webRid,一种是roomId + // roomId是一次性的,用户每次重新开播都会生成一个新的roomId + // roomId一般长度为19位,例如:7376429659866598196 + // webRid是固定的,用户每次开播都是同一个webRid + // webRid一般长度为11-12位,例如:416144012050 + // 这里简单进行判断,如果roomId长度小于15,则认为是webRid + if (roomId.length <= 16) { + var webRid = roomId; + return await getRoomDetailByWebRid(webRid); } + return await getRoomDetailByRoomId(roomId); + } + + /// 通过roomId获取直播间信息 + /// - [roomId] 直播间ID + /// - 返回直播间信息 + Future getRoomDetailByRoomId(String roomId) async { // 读取房间信息 - var roomInfo = await _getRoomInfo(roomId); + var roomData = await _getRoomDataByRoomId(roomId); // 通过房间信息获取WebRid - var webRid = roomInfo["data"]["room"]["owner"]["web_rid"].toString(); + var webRid = roomData["data"]["room"]["owner"]["web_rid"].toString(); // 读取用户唯一ID,用于弹幕连接 // 似乎这个参数不是必须的,先随机生成一个 //var userUniqueId = await _getUserUniqueId(webRid); var userUniqueId = generateRandomNumber(12).toString(); - var room = roomInfo["data"]["room"]; + var room = roomData["data"]["room"]; var owner = room["owner"]; - var roomStatus = (asT(room["status"]) ?? 0) == 2; + var status = asT(room["status"]) ?? 0; + // roomId是一次性的,用户每次重新开播都会生成一个新的roomId + // 所以如果roomId对应的直播间状态不是直播中,就通过webRid获取直播间信息 + if (status == 4) { + var result = await getRoomDetailByWebRid(webRid); + return result; + } + + var roomStatus = status == 2; // 主要是为了获取cookie,用于弹幕websocket连接 var headers = await getRequestHeaders(); return LiveRoomDetail( - roomId: roomId, + roomId: webRid, title: room["title"].toString(), cover: roomStatus ? room["cover"]["url_list"][0].toString() : "", userName: owner["nickname"].toString(), @@ -221,35 +242,100 @@ class DouyinSite implements LiveSite { ); } - /// 通过webRid获取直播间信息,用于兼容旧版本 + /// 通过WebRid获取直播间信息 /// - [webRid] 直播间RID + /// - 返回直播间信息 Future getRoomDetailByWebRid(String webRid) async { - var webRoomInfo = await _getWebRoomInfo(webRid); - var roomId = - webRoomInfo["roomStore"]["roomInfo"]["room"]["id_str"].toString(); + try { + var result = await _getRoomDetailByWebRidApi(webRid); + return result; + } catch (e) { + CoreLog.error(e); + } + return await _getRoomDetailByWebRidHtml(webRid); + } + + /// 通过WebRid访问直播间API,从API中获取直播间信息 + /// - [webRid] 直播间RID + /// - 返回直播间信息 + Future _getRoomDetailByWebRidApi(String webRid) async { + // 读取房间信息 + var data = await _getRoomDataByApi(webRid); + var roomData = data["data"][0]; + var userData = data["user"]; + var roomId = roomData["id_str"].toString(); + + // 读取用户唯一ID,用于弹幕连接 + // 似乎这个参数不是必须的,先随机生成一个 + //var userUniqueId = await _getUserUniqueId(webRid); + var userUniqueId = generateRandomNumber(12).toString(); + + var owner = roomData["owner"]; + + var roomStatus = (asT(roomData["status"]) ?? 0) == 2; + + // 主要是为了获取cookie,用于弹幕websocket连接 + var headers = await getRequestHeaders(); + return LiveRoomDetail( + roomId: webRid, + title: roomData["title"].toString(), + cover: roomStatus ? roomData["cover"]["url_list"][0].toString() : "", + userName: roomStatus + ? owner["nickname"].toString() + : userData["nickname"].toString(), + userAvatar: roomStatus + ? owner["avatar_thumb"]["url_list"][0].toString() + : userData["avatar_thumb"]["url_list"][0].toString(), + online: roomStatus + ? asT(roomData["room_view_stats"]["display_value"]) ?? 0 + : 0, + status: roomStatus, + url: "https://live.douyin.com/$webRid", + introduction: owner?["signature"]?.toString() ?? "", + notice: "", + danmakuData: DouyinDanmakuArgs( + webRid: webRid, + roomId: roomId, + userId: userUniqueId, + cookie: headers["cookie"], + ), + data: roomStatus ? roomData["stream_url"] : {}, + ); + } + + /// 通过WebRid访问直播间网页,从网页HTML中获取直播间信息 + /// - [webRid] 直播间RID + /// - 返回直播间信息 + Future _getRoomDetailByWebRidHtml(String webRid) async { + var roomData = await _getRoomDataByHtml(webRid); + var roomId = roomData["roomStore"]["roomInfo"]["room"]["id_str"].toString(); var userUniqueId = - webRoomInfo["userStore"]["odin"]["user_unique_id"].toString(); + roomData["userStore"]["odin"]["user_unique_id"].toString(); - var roomInfo = await _getRoomInfo(roomId); - var room = roomInfo["data"]["room"]; + var room = roomData["roomStore"]["roomInfo"]["room"]; var owner = room["owner"]; + var anchor = roomData["roomStore"]["roomInfo"]["anchor"]; var roomStatus = (asT(room["status"]) ?? 0) == 2; // 主要是为了获取cookie,用于弹幕websocket连接 var headers = await getRequestHeaders(); return LiveRoomDetail( - roomId: roomId, + roomId: webRid, title: room["title"].toString(), cover: roomStatus ? room["cover"]["url_list"][0].toString() : "", - userName: owner["nickname"].toString(), - userAvatar: owner["avatar_thumb"]["url_list"][0].toString(), + userName: roomStatus + ? owner["nickname"].toString() + : anchor["nickname"].toString(), + userAvatar: roomStatus + ? owner["avatar_thumb"]["url_list"][0].toString() + : anchor["avatar_thumb"]["url_list"][0].toString(), online: roomStatus ? asT(room["room_view_stats"]["display_value"]) ?? 0 : 0, status: roomStatus, url: "https://live.douyin.com/$webRid", - introduction: owner["signature"].toString(), + introduction: owner?["signature"]?.toString() ?? "", notice: "", danmakuData: DouyinDanmakuArgs( webRid: webRid, @@ -257,15 +343,15 @@ class DouyinSite implements LiveSite { userId: userUniqueId, cookie: headers["cookie"], ), - data: room["stream_url"], + data: roomStatus ? room["stream_url"] : {}, ); } - /// 读取用户名的唯一ID + /// 读取用户的唯一ID /// - [webRid] 直播间RID // ignore: unused_element Future _getUserUniqueId(String webRid) async { - var webInfo = await _getWebRoomInfo(webRid); + var webInfo = await _getRoomDataByHtml(webRid); return webInfo["userStore"]["odin"]["user_unique_id"].toString(); } @@ -285,12 +371,16 @@ class DouyinSite implements LiveSite { if (cookie.contains("__ac_nonce")) { dyCookie += "$cookie;"; } + if (cookie.contains("msToken")) { + dyCookie += "$cookie;"; + } }); return dyCookie; } /// 通过webRid获取直播间Web信息 - Future _getWebRoomInfo(String webRid) async { + /// - [webRid] 直播间RID + Future _getRoomDataByHtml(String webRid) async { var dyCookie = await _getWebCookie(webRid); var result = await HttpClient.instance.getText( "https://live.douyin.com/$webRid", @@ -313,13 +403,43 @@ class DouyinSite implements LiveSite { .replaceAll(r"\\", r"\") .replaceAll(']\\n', ""); var renderDataJson = json.decode(str); - return renderDataJson["state"]; } + /// 通过webRid获取直播间Web信息 + /// - [webRid] 直播间RID + Future _getRoomDataByApi(String webRid) async { + var requestHeader = await getRequestHeaders(); + var result = await HttpClient.instance.getJson( + "https://live.douyin.com/webcast/room/web/enter/", + queryParameters: { + "aid": 6383, + "app_name": "douyin_web", + "live_id": 1, + "device_platform": "web", + "enter_from": "web_live", + "web_rid": webRid, + "room_id_str": "", + "enter_source": "", + "Room-Enter-User-Login-Ab": 0, + "is_need_double_stream": false, + "cookie_enabled": true, + "screen_width": 1980, + "screen_height": 1080, + "browser_language": "zh-CN", + "browser_platform": "Win32", + "browser_name": "Edge", + "browser_version": "125.0.0.0" + }, + header: requestHeader, + ); + + return result["data"]; + } + /// 通过roomId获取直播间信息 /// - [roomId] 直播间ID - Future _getRoomInfo(String roomId) async { + Future _getRoomDataByRoomId(String roomId) async { var result = await HttpClient.instance.getJson( 'https://webcast.amemv.com/webcast/room/reflow/info/', queryParameters: { @@ -339,21 +459,55 @@ class DouyinSite implements LiveSite { Future> getPlayQualites( {required LiveRoomDetail detail}) async { List qualities = []; - var qualityData = json.decode( - detail.data["live_core_sdk_data"]["pull_data"]["stream_data"])["data"]; + var qulityList = detail.data["live_core_sdk_data"]["pull_data"]["options"]["qualities"]; - for (var quality in qulityList) { - var qualityItem = LivePlayQuality( - quality: quality["name"], - sort: quality["level"], - data: [ - qualityData[quality["sdk_key"]]["main"]["flv"].toString(), - qualityData[quality["sdk_key"]]["main"]["hls"].toString(), - ], - ); - qualities.add(qualityItem); + + if (detail.data["live_core_sdk_data"]["pull_data"]["stream_data"] + is String) { + var flvList = + (detail.data["flv_pull_url"] as Map).values.cast().toList(); + var hlsList = (detail.data["hls_pull_url_map"] as Map) + .values + .cast() + .toList(); + for (var quality in qulityList) { + int level = quality["level"]; + List urls = []; + var flvIndex = flvList.length - level; + if (flvIndex >= 0 && flvIndex < flvList.length) { + urls.add(flvList[flvIndex]); + } + var hlsIndex = hlsList.length - level; + if (hlsIndex >= 0 && hlsIndex < hlsList.length) { + urls.add(hlsList[hlsIndex]); + } + var qualityItem = LivePlayQuality( + quality: quality["name"], + sort: level, + data: urls, + ); + + qualities.add(qualityItem); + } + } else { + var qualityData = json.decode(detail.data["live_core_sdk_data"] + ["pull_data"]["stream_data"])["data"]; + for (var quality in qulityList) { + var qualityItem = LivePlayQuality( + quality: quality["name"], + sort: quality["level"], + data: [ + qualityData[quality["sdk_key"]]["main"]["flv"].toString(), + qualityData[quality["sdk_key"]]["main"]["hls"].toString(), + ], + ); + qualities.add(qualityItem); + } } + // var qualityData = json.decode( + // detail.data["live_core_sdk_data"]["pull_data"]["stream_data"])["data"]; + qualities.sort((a, b) => b.sort.compareTo(a.sort)); return qualities; } @@ -457,12 +611,8 @@ class DouyinSite implements LiveSite { @override Future getLiveStatus({required String roomId}) async { - if (roomId.length < 15) { - var result = await _getWebRoomInfo(roomId); - return result["roomStore"]["roomInfo"]["room"]["status"] == 2; - } - var result = await _getRoomInfo(roomId); - return (asT(result["data"]["room"]["status"]) ?? 0) == 2; + var result = await getRoomDetail(roomId: roomId); + return result.status; } @override From 364c1f2125c2ea9d7cd24946a74a104a1c2dffdb Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Thu, 6 Jun 2024 17:05:58 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=97=E9=B1=BC?= =?UTF-8?q?=E7=9B=B4=E6=92=AD=E7=8A=B6=E6=80=81=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple_live_core/lib/src/douyu_site.dart | 38 ++++++++++++++---------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/simple_live_core/lib/src/douyu_site.dart b/simple_live_core/lib/src/douyu_site.dart index 2ead73c..2681611 100644 --- a/simple_live_core/lib/src/douyu_site.dart +++ b/simple_live_core/lib/src/douyu_site.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:math'; @@ -174,20 +175,7 @@ class DouyuSite implements LiveSite { @override Future getRoomDetail({required String roomId}) async { - var result = await HttpClient.instance.getJson( - "https://www.douyu.com/betard/$roomId", - queryParameters: {}, - header: { - 'referer': 'https://www.douyu.com/$roomId', - 'user-agent': - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43', - }); - Map roomInfo; - if (result is String) { - roomInfo = json.decode(result)["room"]; - } else { - roomInfo = result["room"]; - } + Map roomInfo = await _getRoomInfo(roomId); var jsEncResult = await HttpClient.instance.getText( "https://www.douyu.com/swf_api/homeH5Enc?rids=$roomId", @@ -252,6 +240,24 @@ class DouyuSite implements LiveSite { return LiveSearchRoomResult(hasMore: hasMore, items: items); } + Future _getRoomInfo(String roomId) async { + var result = await HttpClient.instance.getJson( + "https://www.douyu.com/betard/$roomId", + queryParameters: {}, + header: { + 'referer': 'https://www.douyu.com/$roomId', + 'user-agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.43', + }); + Map roomInfo; + if (result is String) { + roomInfo = json.decode(result)["room"]; + } else { + roomInfo = result["room"]; + } + return roomInfo; + } + //生成指定长度的16进制随机字符串 String generateRandomString(int length) { var random = Random.secure(); @@ -303,8 +309,8 @@ class DouyuSite implements LiveSite { @override Future getLiveStatus({required String roomId}) async { - var detail = await getRoomDetail(roomId: roomId); - return detail.status; + var roomInfo = await _getRoomInfo(roomId); + return roomInfo["show_status"] == 1 && roomInfo["videoLoop"] != 1; } Future getPlayArgs(String html, String rid) async { From 2283b90ca8779f188c721c71e9eaf2c6b256e491 Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Thu, 6 Jun 2024 17:14:43 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=99=8E=E7=89=99?= =?UTF-8?q?=E7=9B=B4=E6=92=AD=E7=8A=B6=E6=80=81=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple_live_core/lib/src/huya_site.dart | 132 +++++++++++------------- 1 file changed, 62 insertions(+), 70 deletions(-) diff --git a/simple_live_core/lib/src/huya_site.dart b/simple_live_core/lib/src/huya_site.dart index 9f7ac30..df36f77 100644 --- a/simple_live_core/lib/src/huya_site.dart +++ b/simple_live_core/lib/src/huya_site.dart @@ -219,37 +219,18 @@ class HuyaSite implements LiveSite { @override Future getRoomDetail({required String roomId}) async { - var resultText = await HttpClient.instance.getText( - "https://m.huya.com/$roomId", - queryParameters: {}, - header: { - "user-agent": kUserAgent, - }, - ); - var text = RegExp( - r"window\.HNF_GLOBAL_INIT.=.\{[\s\S]*?\}[\s\S]*?", - multiLine: false) - .firstMatch(resultText) - ?.group(0); - var jsonText = text! - .replaceAll(RegExp(r"window\.HNF_GLOBAL_INIT.=."), '') - .replaceAll("", "") - .replaceAllMapped(RegExp(r'function.*?\(.*?\).\{[\s\S]*?\}'), (match) { - return '""'; - }); - - var jsonObj = json.decode(jsonText); + var roomInfo = await _getRoomInfo(roomId); + var tLiveInfo = roomInfo["roomInfo"]["tLiveInfo"]; + var tProfileInfo = roomInfo["roomInfo"]["tProfileInfo"]; - var title = - jsonObj["roomInfo"]["tLiveInfo"]["sIntroduction"]?.toString() ?? ""; + var title = tLiveInfo["sIntroduction"]?.toString() ?? ""; if (title.isEmpty) { - title = jsonObj["roomInfo"]["tLiveInfo"]["sRoomName"]?.toString() ?? ""; + title = tLiveInfo["sRoomName"]?.toString() ?? ""; } var huyaLines = []; var huyaBiterates = []; //读取可用线路 - var lines = jsonObj["roomInfo"]["tLiveInfo"]["tLiveStreamInfo"] - ["vStreamInfo"]["value"]; + var lines = tLiveInfo["tLiveStreamInfo"]["vStreamInfo"]["value"]; for (var item in lines) { if ((item["sFlvUrl"]?.toString() ?? "").isNotEmpty) { huyaLines.add(HuyaLineModel( @@ -263,8 +244,7 @@ class HuyaSite implements LiveSite { } //清晰度 - var biterates = jsonObj["roomInfo"]["tLiveInfo"]["tLiveStreamInfo"] - ["vBitRateInfo"]["value"]; + var biterates = tLiveInfo["tLiveStreamInfo"]["vBitRateInfo"]["value"]; for (var item in biterates) { var name = item["sDisplayName"].toString(); if (name.contains("HDR")) { @@ -276,38 +256,65 @@ class HuyaSite implements LiveSite { )); } + var topSid = roomInfo["topSid"]; + var subSid = roomInfo["subSid"]; + + return LiveRoomDetail( + cover: tLiveInfo["sScreenshot"].toString(), + online: tLiveInfo["lTotalCount"], + roomId: tLiveInfo["lProfileRoom"].toString(), + title: title, + userName: tProfileInfo["sNick"].toString(), + userAvatar: tProfileInfo["sAvatar180"].toString(), + introduction: tLiveInfo["sIntroduction"].toString(), + notice: roomInfo["welcomeText"].toString(), + status: roomInfo["roomInfo"]["eLiveStatus"] == 2, + data: HuyaUrlDataModel( + url: + "https:${utf8.decode(base64.decode(roomInfo["roomProfile"]["liveLineUrl"].toString()))}", + lines: huyaLines, + bitRates: huyaBiterates, + uid: getUid(t: 13, e: 10), + ), + danmakuData: HuyaDanmakuArgs( + ayyuid: tLiveInfo["lYyid"] ?? 0, + topSid: topSid ?? 0, + subSid: subSid ?? 0, + ), + url: "https://www.huya.com/$roomId", + ); + } + + Future _getRoomInfo(String roomId) async { + var resultText = await HttpClient.instance.getText( + "https://m.huya.com/$roomId", + queryParameters: {}, + header: { + "user-agent": kUserAgent, + }, + ); + var text = RegExp( + r"window\.HNF_GLOBAL_INIT.=.\{[\s\S]*?\}[\s\S]*?", + multiLine: false) + .firstMatch(resultText) + ?.group(0); + var jsonText = text! + .replaceAll(RegExp(r"window\.HNF_GLOBAL_INIT.=."), '') + .replaceAll("", "") + .replaceAllMapped(RegExp(r'function.*?\(.*?\).\{[\s\S]*?\}'), (match) { + return '""'; + }); + + var jsonObj = json.decode(jsonText); var topSid = int.tryParse( RegExp(r'lChannelId":([0-9]+)').firstMatch(resultText)?.group(1) ?? "0"); var subSid = int.tryParse( RegExp(r'lSubChannelId":([0-9]+)').firstMatch(resultText)?.group(1) ?? "0"); - - return LiveRoomDetail( - cover: jsonObj["roomInfo"]["tLiveInfo"]["sScreenshot"].toString(), - online: jsonObj["roomInfo"]["tLiveInfo"]["lTotalCount"], - roomId: jsonObj["roomInfo"]["tLiveInfo"]["lProfileRoom"].toString(), - title: title, - userName: jsonObj["roomInfo"]["tProfileInfo"]["sNick"].toString(), - userAvatar: - jsonObj["roomInfo"]["tProfileInfo"]["sAvatar180"].toString(), - introduction: - jsonObj["roomInfo"]["tLiveInfo"]["sIntroduction"].toString(), - notice: jsonObj["welcomeText"].toString(), - status: jsonObj["roomInfo"]["eLiveStatus"] == 2, - data: HuyaUrlDataModel( - url: - "https:${utf8.decode(base64.decode(jsonObj["roomProfile"]["liveLineUrl"].toString()))}", - lines: huyaLines, - bitRates: huyaBiterates, - uid: getUid(t: 13, e: 10), - ), - danmakuData: HuyaDanmakuArgs( - ayyuid: jsonObj["roomInfo"]["tLiveInfo"]["lYyid"] ?? 0, - topSid: topSid ?? 0, - subSid: subSid ?? 0, - ), - url: "https://www.huya.com/$roomId"); + jsonObj["topSid"] = topSid; + jsonObj["subSid"] = subSid; + return jsonObj; } @override @@ -387,23 +394,8 @@ class HuyaSite implements LiveSite { @override Future getLiveStatus({required String roomId}) async { - var resultText = await HttpClient.instance - .getText("https://m.huya.com/$roomId", queryParameters: {}, header: { - "user-agent": kUserAgent, - }); - var text = RegExp( - r"window\.HNF_GLOBAL_INIT.=.\{[\s\S]*?\}[\s\S]*?", - multiLine: false) - .firstMatch(resultText) - ?.group(0); - var jsonText = text! - .replaceAll(RegExp(r"window\.HNF_GLOBAL_INIT.=."), '') - .replaceAll("", "") - .replaceAllMapped(RegExp(r'function.*?\(.*?\).\{[\s\S]*?\}'), (match) { - return '""'; - }); - var jsonObj = json.decode(jsonText); - return jsonObj["roomInfo"]["eLiveStatus"] == 2; + var roomInfo = await _getRoomInfo(roomId); + return roomInfo["roomInfo"]["eLiveStatus"] == 2; } /// 匿名登录获取uid From de7eb4798d0a58707da97d73e41346575751291f Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Thu, 6 Jun 2024 17:23:16 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8A=96=E9=9F=B3?= =?UTF-8?q?=E9=83=A8=E5=88=86=E6=B8=85=E6=99=B0=E5=BA=A6=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/simple_live_core_example.dart | 2 +- simple_live_core/lib/src/douyin_site.dart | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/simple_live_core/example/simple_live_core_example.dart b/simple_live_core/example/simple_live_core_example.dart index 45212ec..bfc777d 100644 --- a/simple_live_core/example/simple_live_core_example.dart +++ b/simple_live_core/example/simple_live_core_example.dart @@ -20,7 +20,7 @@ void main() async { }; //var categores = await site.getCategores(); //print(categores.length); - var detail = await site.getRoomDetail(roomId: "7376294819431238409"); + var detail = await site.getRoomDetail(roomId: "320875656639"); var playQualites = await site.getPlayQualites(detail: detail); var playUrls = await site.getPlayUrls(detail: detail, quality: playQualites.first); diff --git a/simple_live_core/lib/src/douyin_site.dart b/simple_live_core/lib/src/douyin_site.dart index 336ec20..cdb7338 100644 --- a/simple_live_core/lib/src/douyin_site.dart +++ b/simple_live_core/lib/src/douyin_site.dart @@ -493,16 +493,28 @@ class DouyinSite implements LiveSite { } else { var qualityData = json.decode(detail.data["live_core_sdk_data"] ["pull_data"]["stream_data"])["data"]; + for (var quality in qulityList) { + List urls = []; + var flvUrl = + qualityData[quality["sdk_key"]]?["main"]?["flv"]?.toString(); + + if (flvUrl != null && flvUrl.isNotEmpty) { + urls.add(flvUrl); + } + var hlsUrl = + qualityData[quality["sdk_key"]]?["main"]?["hls"]?.toString(); + if (hlsUrl != null && hlsUrl.isNotEmpty) { + urls.add(hlsUrl); + } var qualityItem = LivePlayQuality( quality: quality["name"], sort: quality["level"], - data: [ - qualityData[quality["sdk_key"]]["main"]["flv"].toString(), - qualityData[quality["sdk_key"]]["main"]["hls"].toString(), - ], + data: urls, ); - qualities.add(qualityItem); + if (urls.isNotEmpty) { + qualities.add(qualityItem); + } } } // var qualityData = json.decode( From a05951eabb60c1b3a78c5638a977ddd987306a02 Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Thu, 6 Jun 2024 17:53:05 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E7=9B=B4=E6=92=AD=E9=97=B4=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=9F=A5=E7=9C=8B=E6=92=AD=E6=94=BE=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/modules/live_room/live_room_page.dart | 9 +++++ .../live_room/player/player_controller.dart | 36 +++++++++++-------- .../lib/modules/user/user_page.dart | 22 ++++++------ simple_live_app/pubspec.yaml | 2 +- 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/simple_live_app/lib/modules/live_room/live_room_page.dart b/simple_live_app/lib/modules/live_room/live_room_page.dart index e87e015..e73131a 100644 --- a/simple_live_app/lib/modules/live_room/live_room_page.dart +++ b/simple_live_app/lib/modules/live_room/live_room_page.dart @@ -847,6 +847,15 @@ class LiveRoomPage extends GetView { controller.openNaviteAPP(); }, ), + ListTile( + leading: const Icon(Icons.info_outline_rounded), + title: const Text("播放信息"), + trailing: const Icon(Icons.chevron_right), + onTap: () { + Get.back(); + controller.showDebugInfo(); + }, + ), ], ), ), diff --git a/simple_live_app/lib/modules/live_room/player/player_controller.dart b/simple_live_app/lib/modules/live_room/player/player_controller.dart index 107ac03..7e53417 100644 --- a/simple_live_app/lib/modules/live_room/player/player_controller.dart +++ b/simple_live_app/lib/modules/live_room/player/player_controller.dart @@ -699,24 +699,10 @@ class PlayerController extends BaseController void mediaError(String error) {} void showDebugInfo() { - if (lockControlsState.value && fullScreenState.value) { - return; - } Utils.showBottomSheet( title: "播放信息", child: ListView( children: [ - ListTile( - title: const Text("Media"), - subtitle: Text(player.state.playlist.toString()), - onTap: () { - Clipboard.setData( - ClipboardData( - text: "Media\n${player.state.playlist}", - ), - ); - }, - ), ListTile( title: const Text("Resolution"), subtitle: Text('${player.state.width}x${player.state.height}'), @@ -751,6 +737,17 @@ class PlayerController extends BaseController ); }, ), + ListTile( + title: const Text("Media"), + subtitle: Text(player.state.playlist.toString()), + onTap: () { + Clipboard.setData( + ClipboardData( + text: "Media\n${player.state.playlist}", + ), + ); + }, + ), ListTile( title: const Text("AudioTrack"), subtitle: Text(player.state.track.audio.toString()), @@ -784,6 +781,17 @@ class PlayerController extends BaseController ); }, ), + ListTile( + title: const Text("Volume"), + subtitle: Text(player.state.volume.toString()), + onTap: () { + Clipboard.setData( + ClipboardData( + text: "Volume\n${player.state.volume}", + ), + ); + }, + ), ], ), ); diff --git a/simple_live_app/lib/modules/user/user_page.dart b/simple_live_app/lib/modules/user/user_page.dart index 42a6601..64b1c77 100644 --- a/simple_live_app/lib/modules/user/user_page.dart +++ b/simple_live_app/lib/modules/user/user_page.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; @@ -193,17 +194,18 @@ class UserPage extends StatelessWidget { Get.toNamed(RoutePath.kSettingsOther); }, ), - ListTile( - leading: const Icon(Remix.apps_line), - title: const Text("测试"), - trailing: const Icon( - Icons.chevron_right, - color: Colors.grey, + if (kDebugMode) + ListTile( + leading: const Icon(Remix.apps_line), + title: const Text("测试"), + trailing: const Icon( + Icons.chevron_right, + color: Colors.grey, + ), + onTap: () { + Get.toNamed(RoutePath.kTest); + }, ), - onTap: () { - Get.toNamed(RoutePath.kTest); - }, - ), ], ), Divider( diff --git a/simple_live_app/pubspec.yaml b/simple_live_app/pubspec.yaml index aa422ae..a5ea44d 100644 --- a/simple_live_app/pubspec.yaml +++ b/simple_live_app/pubspec.yaml @@ -1,5 +1,5 @@ name: simple_live_app -version: 1.6.0+10600 +version: 1.6.1+10601 publish_to: none description: "Simple Live APP" environment: From a602b4e1e125d8381f14763871f806404fe47657 Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Thu, 6 Jun 2024 18:11:07 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8A=96=E9=9F=B3?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96=E5=8E=9F=E7=94=BB=20#429?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/simple_live_core_example.dart | 2 +- simple_live_core/lib/src/douyin_site.dart | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/simple_live_core/example/simple_live_core_example.dart b/simple_live_core/example/simple_live_core_example.dart index bfc777d..1565b5f 100644 --- a/simple_live_core/example/simple_live_core_example.dart +++ b/simple_live_core/example/simple_live_core_example.dart @@ -20,7 +20,7 @@ void main() async { }; //var categores = await site.getCategores(); //print(categores.length); - var detail = await site.getRoomDetail(roomId: "320875656639"); + var detail = await site.getRoomDetail(roomId: "121118665759"); var playQualites = await site.getPlayQualites(detail: detail); var playUrls = await site.getPlayUrls(detail: detail, quality: playQualites.first); diff --git a/simple_live_core/lib/src/douyin_site.dart b/simple_live_core/lib/src/douyin_site.dart index cdb7338..a141a51 100644 --- a/simple_live_core/lib/src/douyin_site.dart +++ b/simple_live_core/lib/src/douyin_site.dart @@ -462,9 +462,11 @@ class DouyinSite implements LiveSite { var qulityList = detail.data["live_core_sdk_data"]["pull_data"]["options"]["qualities"]; + var streamData = detail.data["live_core_sdk_data"]["pull_data"] + ["stream_data"] + .toString(); - if (detail.data["live_core_sdk_data"]["pull_data"]["stream_data"] - is String) { + if (!streamData.startsWith('{')) { var flvList = (detail.data["flv_pull_url"] as Map).values.cast().toList(); var hlsList = (detail.data["hls_pull_url_map"] as Map) @@ -487,12 +489,12 @@ class DouyinSite implements LiveSite { sort: level, data: urls, ); - - qualities.add(qualityItem); + if (urls.isNotEmpty) { + qualities.add(qualityItem); + } } } else { - var qualityData = json.decode(detail.data["live_core_sdk_data"] - ["pull_data"]["stream_data"])["data"]; + var qualityData = json.decode(streamData)["data"]; for (var quality in qulityList) { List urls = []; From c54569f6eb9f5d7a13246a83a95d17e878ef6d6a Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Fri, 7 Jun 2024 14:18:30 +0800 Subject: [PATCH 10/13] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E9=80=9A=E8=BF=87RoomID=E8=8E=B7=E5=8F=96=E5=8E=9F=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple_live_core/example/simple_live_core_example.dart | 2 +- simple_live_core/lib/src/douyin_site.dart | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/simple_live_core/example/simple_live_core_example.dart b/simple_live_core/example/simple_live_core_example.dart index 1565b5f..0ccf28f 100644 --- a/simple_live_core/example/simple_live_core_example.dart +++ b/simple_live_core/example/simple_live_core_example.dart @@ -20,7 +20,7 @@ void main() async { }; //var categores = await site.getCategores(); //print(categores.length); - var detail = await site.getRoomDetail(roomId: "121118665759"); + var detail = await site.getRoomDetail(roomId: "7377636198720015167"); var playQualites = await site.getPlayQualites(detail: detail); var playUrls = await site.getPlayUrls(detail: detail, quality: playQualites.first); diff --git a/simple_live_core/lib/src/douyin_site.dart b/simple_live_core/lib/src/douyin_site.dart index a141a51..2b15b9c 100644 --- a/simple_live_core/lib/src/douyin_site.dart +++ b/simple_live_core/lib/src/douyin_site.dart @@ -448,7 +448,7 @@ class DouyinSite implements LiveSite { "room_id": roomId, "sec_user_id": "", "version_code": "99.99.99", - "app_id": 1128, + "app_id": 6383, }, header: await getRequestHeaders(), ); @@ -494,8 +494,7 @@ class DouyinSite implements LiveSite { } } } else { - var qualityData = json.decode(streamData)["data"]; - + var qualityData = json.decode(streamData)["data"] as Map; for (var quality in qulityList) { List urls = []; var flvUrl = From 135152dc497c9805cb7936c025dc7df5228df434 Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Fri, 7 Jun 2024 15:43:02 +0800 Subject: [PATCH 11/13] Release 1.6.2 / TV 1.0.9 --- assets/app_version.json | 6 +- assets/tv_app_version.json | 6 +- .../lib/modules/user/test_page.dart | 111 ------------------ simple_live_app/lib/routes/app_pages.dart | 10 -- simple_live_app/pubspec.yaml | 7 +- simple_live_core/pubspec.yaml | 2 +- simple_live_tv_app/pubspec.lock | 2 +- simple_live_tv_app/pubspec.yaml | 2 +- 8 files changed, 10 insertions(+), 136 deletions(-) delete mode 100644 simple_live_app/lib/modules/user/test_page.dart diff --git a/assets/app_version.json b/assets/app_version.json index 68643e0..4ff27c9 100644 --- a/assets/app_version.json +++ b/assets/app_version.json @@ -1,7 +1,7 @@ { - "version": "1.6.0", - "version_num": 10600, - "version_desc": "- 修复MacOS打开同步失败 #351\n- 修复Windows返回时亮度调节至最高 #332\n- 修复虎牙分类加载失败 #366\n- 修复虎牙无法播放问题 #409\n- 修复链接跳转时虚拟导航条显示错误 #373\n- 修复播放器锁定时依旧触发长按事件\n- 支持调整弹幕字重 #372\n- 支持日志记录\n- 支持抖音手机端分享链接解析 #376\n- 支持复制直播间链接\n- 支持滑动删除历史记录 #231\n- 支持自定义视频输出驱动\n- PC页面增加刷新按钮\n- 优化桌面小窗播放\n- 优化关注列表加载\n- 优化直播间加载错误的处理\n- 统一全平台图标,安卓支持主题图标 #140 #112\n- 尝试使用WebView实现抖音搜索 #379", + "version": "1.6.2", + "version_num": 10602, + "version_desc": "- 修复抖音无法读取直播状态 #431\n - 修复抖音无法读取原画 #429\n- 优化直播状态读取", "prerelease":false, "download_url": "https://github.com/xiaoyaocz/dart_simple_live/releases" } \ No newline at end of file diff --git a/assets/tv_app_version.json b/assets/tv_app_version.json index 6edbdec..8e70361 100644 --- a/assets/tv_app_version.json +++ b/assets/tv_app_version.json @@ -1,7 +1,7 @@ { - "version": "1.0.8", - "version_num": 10008, - "version_desc": "- 修复虎牙播放问题\n- TV增加Banner图标\n- 优化使用体验", + "version": "1.0.9", + "version_num": 10009, + "version_desc": "- 修复抖音无法读取原画\n- 优化直播状态读取", "prerelease":true, "download_url": "https://github.com/xiaoyaocz/dart_simple_live/releases" } \ No newline at end of file diff --git a/simple_live_app/lib/modules/user/test_page.dart b/simple_live_app/lib/modules/user/test_page.dart deleted file mode 100644 index 7a9b286..0000000 --- a/simple_live_app/lib/modules/user/test_page.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:get/get.dart'; -import 'package:sensors_plus/sensors_plus.dart'; -import 'package:simple_live_app/app/log.dart'; -import 'package:motion_sensors/motion_sensors.dart' as motion_sensors; - -class TestPage extends GetView { - const TestPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.black, - body: Center( - child: Obx( - () => Text( - controller.orientation.value, - style: const TextStyle(fontSize: 32, color: Colors.white), - ), - ), - ), - ); - } -} - -class TestController extends GetxController { - var orientation = "".obs; - - @override - void onInit() { - setLandscape(); - super.onInit(); - } - - void setLandscape() async { - await SystemChrome.setPreferredOrientations([ - DeviceOrientation.landscapeLeft, - ]); - orientation.value = "LANDSCAPE LEFT"; - listenSensor(); - } - - StreamSubscription? _streamSubscription; - StreamSubscription? _orientationStreamSubscription; - void listenSensor() { - // 监听传感器事件,获取当前设备的方向 - // _streamSubscription = accelerometerEventStream( - // samplingPeriod: const Duration(seconds: 1), - // ).listen((AccelerometerEvent event) { - // var x = event.x; - // var y = event.y; - - // var newOrientation = ""; - // if (x >= 9.0 && y < 9.0 && y >= -9.0) { - // newOrientation = "LANDSCAPE LEFT"; - // } else if (x <= -9.0 && y < 9.0 && y >= -9.0) { - // newOrientation = "LANDSCAPE RIGHT"; - // } - // if (orientation.value != newOrientation && newOrientation.isNotEmpty) { - // orientation.value = newOrientation; - // if (orientation.value == "LANDSCAPE RIGHT") { - // SystemChrome.setPreferredOrientations([ - // DeviceOrientation.landscapeRight, - // ]); - // } else { - // SystemChrome.setPreferredOrientations([ - // DeviceOrientation.landscapeLeft, - // ]); - // } - // Log.d("newOrientation: $newOrientation"); - // } - // }); - - _orientationStreamSubscription = - motion_sensors.motionSensors.accelerometer.listen((event) { - var x = event.x; - var y = event.y; - - var newOrientation = ""; - if (x >= 9.0 && y < 9.0 && y >= -9.0) { - newOrientation = "LANDSCAPE LEFT"; - } else if (x <= -9.0 && y < 9.0 && y >= -9.0) { - newOrientation = "LANDSCAPE RIGHT"; - } - if (orientation.value != newOrientation && newOrientation.isNotEmpty) { - orientation.value = newOrientation; - if (orientation.value == "LANDSCAPE RIGHT") { - SystemChrome.setPreferredOrientations([ - DeviceOrientation.landscapeRight, - ]); - } else { - SystemChrome.setPreferredOrientations([ - DeviceOrientation.landscapeLeft, - ]); - } - Log.d("newOrientation: $newOrientation"); - } - }); - } - - @override - void onClose() { - SystemChrome.setPreferredOrientations(DeviceOrientation.values); - _streamSubscription?.cancel(); - _orientationStreamSubscription?.cancel(); - super.onClose(); - } -} diff --git a/simple_live_app/lib/routes/app_pages.dart b/simple_live_app/lib/routes/app_pages.dart index f187e5c..665df83 100644 --- a/simple_live_app/lib/routes/app_pages.dart +++ b/simple_live_app/lib/routes/app_pages.dart @@ -36,7 +36,6 @@ import 'package:simple_live_app/modules/user/indexed_settings/indexed_settings_p import 'package:simple_live_app/modules/user/other/other_settings_controller.dart'; import 'package:simple_live_app/modules/user/other/other_settings_page.dart'; import 'package:simple_live_app/modules/user/play_settings_page.dart'; -import 'package:simple_live_app/modules/user/test_page.dart'; import '../modules/indexed/indexed_page.dart'; import 'route_path.dart'; @@ -203,14 +202,5 @@ class AppPages { BindingsBuilder.put(() => OtherSettingsController()), ], ), - - //测试页面 - GetPage( - name: RoutePath.kTest, - page: () => const TestPage(), - bindings: [ - BindingsBuilder.put(() => TestController()), - ], - ), ]; } diff --git a/simple_live_app/pubspec.yaml b/simple_live_app/pubspec.yaml index a5ea44d..ef43f65 100644 --- a/simple_live_app/pubspec.yaml +++ b/simple_live_app/pubspec.yaml @@ -1,5 +1,5 @@ name: simple_live_app -version: 1.6.1+10601 +version: 1.6.2+10602 publish_to: none description: "Simple Live APP" environment: @@ -57,11 +57,6 @@ dependencies: flutter_inappwebview: ^5.8.0 #WebView connectivity_plus: ^6.0.3 #网络状态 qr_code_scanner: ^1.0.1 #二维码扫描 - sensors_plus: ^5.0.1 #传感器 - motion_sensors: - git: - url: https://github.com/zesage/motion_sensors.git - ref: master # 网络相关 shelf: ^1.4.1 diff --git a/simple_live_core/pubspec.yaml b/simple_live_core/pubspec.yaml index 94524c7..0c2d772 100644 --- a/simple_live_core/pubspec.yaml +++ b/simple_live_core/pubspec.yaml @@ -1,5 +1,5 @@ name: simple_live_core -version: 1.0.2 +version: 1.0.3 description: "聚合直播核心库" repository: https://github.com/xiaoyaocz/simple_live_client publish_to: "none" diff --git a/simple_live_tv_app/pubspec.lock b/simple_live_tv_app/pubspec.lock index df46591..5ed6ec1 100644 --- a/simple_live_tv_app/pubspec.lock +++ b/simple_live_tv_app/pubspec.lock @@ -712,7 +712,7 @@ packages: path: "../simple_live_core" relative: true source: path - version: "1.0.2" + version: "1.0.3" sky_engine: dependency: transitive description: flutter diff --git a/simple_live_tv_app/pubspec.yaml b/simple_live_tv_app/pubspec.yaml index 29bd1b7..2454668 100644 --- a/simple_live_tv_app/pubspec.yaml +++ b/simple_live_tv_app/pubspec.yaml @@ -1,7 +1,7 @@ name: simple_live_tv_app description: A new Flutter project. publish_to: 'none' -version: 1.0.8+10008 +version: 1.0.9+10009 environment: sdk: '>=3.1.2 <4.0.0' From 950f94bf2a08622dd8e4a305f1bc6637eeb9b778 Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Fri, 7 Jun 2024 15:59:56 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=E6=96=97=E9=B1=BC=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=8D=E4=BD=BF=E7=94=A8PCDN=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/simple_live_core_example.dart | 5 +++-- simple_live_core/lib/src/douyu_site.dart | 11 +++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/simple_live_core/example/simple_live_core_example.dart b/simple_live_core/example/simple_live_core_example.dart index 0ccf28f..2833297 100644 --- a/simple_live_core/example/simple_live_core_example.dart +++ b/simple_live_core/example/simple_live_core_example.dart @@ -3,7 +3,7 @@ import 'package:simple_live_core/simple_live_core.dart'; void main() async { CoreLog.enableLog = true; CoreLog.requestLogType = RequestLogType.short; - LiveSite site = DouyinSite(); + LiveSite site = DouyuSite(); var danmaku = site.getDanmaku(); danmaku.onMessage = (event) { if (event.type == LiveMessageType.chat) { @@ -20,8 +20,9 @@ void main() async { }; //var categores = await site.getCategores(); //print(categores.length); - var detail = await site.getRoomDetail(roomId: "7377636198720015167"); + var detail = await site.getRoomDetail(roomId: "687423"); var playQualites = await site.getPlayQualites(detail: detail); + print(playQualites); var playUrls = await site.getPlayUrls(detail: detail, quality: playQualites.first); for (var element in playUrls) { diff --git a/simple_live_core/lib/src/douyu_site.dart b/simple_live_core/lib/src/douyu_site.dart index 2681611..0d23d3c 100644 --- a/simple_live_core/lib/src/douyu_site.dart +++ b/simple_live_core/lib/src/douyu_site.dart @@ -105,6 +105,17 @@ class DouyuSite implements LiveSite { for (var item in result["data"]["cdnsWithName"]) { cdns.add(item["cdn"].toString()); } + + // 如果cdn以scdn开头,将其放到最后 + cdns.sort((a, b) { + if (a.startsWith("scdn") && !b.startsWith("scdn")) { + return 1; + } else if (!a.startsWith("scdn") && b.startsWith("scdn")) { + return -1; + } + return 0; + }); + for (var item in result["data"]["multirates"]) { qualities.add(LivePlayQuality( quality: item["name"].toString(), From cbe50a8af3aaaa13eb54850cbb779df65720b1fe Mon Sep 17 00:00:00 2001 From: xiaoyaocz Date: Fri, 7 Jun 2024 16:04:03 +0800 Subject: [PATCH 13/13] Release 1.6.3 / TV 1.1.0 --- assets/app_version.json | 6 +++--- assets/tv_app_version.json | 6 +++--- simple_live_app/pubspec.yaml | 2 +- simple_live_tv_app/pubspec.yaml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/app_version.json b/assets/app_version.json index 4ff27c9..3c9fff9 100644 --- a/assets/app_version.json +++ b/assets/app_version.json @@ -1,7 +1,7 @@ { - "version": "1.6.2", - "version_num": 10602, - "version_desc": "- 修复抖音无法读取直播状态 #431\n - 修复抖音无法读取原画 #429\n- 优化直播状态读取", + "version": "1.6.3", + "version_num": 10603, + "version_desc": "- 修复抖音无法读取直播状态 #431\n- 修复抖音无法读取原画 #429\n- 优化直播状态读取\n-斗鱼默认不使用PCDN链接", "prerelease":false, "download_url": "https://github.com/xiaoyaocz/dart_simple_live/releases" } \ No newline at end of file diff --git a/assets/tv_app_version.json b/assets/tv_app_version.json index 8e70361..d9136f8 100644 --- a/assets/tv_app_version.json +++ b/assets/tv_app_version.json @@ -1,7 +1,7 @@ { - "version": "1.0.9", - "version_num": 10009, - "version_desc": "- 修复抖音无法读取原画\n- 优化直播状态读取", + "version": "1.1.0", + "version_num": 10100, + "version_desc": "- 修复抖音无法读取原画\n- 优化直播状态读取\n-斗鱼默认不使用PCDN链接", "prerelease":true, "download_url": "https://github.com/xiaoyaocz/dart_simple_live/releases" } \ No newline at end of file diff --git a/simple_live_app/pubspec.yaml b/simple_live_app/pubspec.yaml index ef43f65..eab097f 100644 --- a/simple_live_app/pubspec.yaml +++ b/simple_live_app/pubspec.yaml @@ -1,5 +1,5 @@ name: simple_live_app -version: 1.6.2+10602 +version: 1.6.3+10603 publish_to: none description: "Simple Live APP" environment: diff --git a/simple_live_tv_app/pubspec.yaml b/simple_live_tv_app/pubspec.yaml index 2454668..bb81dde 100644 --- a/simple_live_tv_app/pubspec.yaml +++ b/simple_live_tv_app/pubspec.yaml @@ -1,7 +1,7 @@ name: simple_live_tv_app description: A new Flutter project. publish_to: 'none' -version: 1.0.9+10009 +version: 1.1.0+10100 environment: sdk: '>=3.1.2 <4.0.0'