当前位置: 首页 > news >正文

flutter缓存网络视频到本地,可离线观看

记录一下解决问题的过程,希望自己以后可以参考看看,解决更多的问题。

需求:flutter 缓存网络视频文件,可离线观看。

解决:

1,flutter APP视频播放组件调整;

2,找到视频播放组件,传入url解析的地方;

 _meeduPlayerController.setDataSource(DataSource(//指定是网络类型的数据type: DataSourceType.network,//设置url参数source: widget.videoUrl != ""? widget.videoUrl: "https://movietrailers.apple.com/movies/paramount/the-spongebob-movie-sponge-on-the-run/the-spongebob-movie-sponge-on-the-run-big-game_h720p.mov",httpHeaders: {"Range": "bytes=0-1023"},),autoplay: !background && widget.autoplay,);

3,那也就是无网路的时候播放本地已经缓存了的对应url的对应视频,先在没有缓存的时候,缓存该文件

        3.1,添加缓存(保存视频)功能依赖

                3.1.1,在视频播放依赖包中添加缓存依赖:flutter_cache_manager: ^3.4.1

                3.1.2,添加基于这个新依赖的功能代码:

import 'package:flutter_cache_manager/flutter_cache_manager.dart';class CustomVideoCacheManager {static const key = 'customCacheKey';static final CacheManager instance = CacheManager(Config(key,maxNrOfCacheObjects: 50, // 最多缓存 50 个视频// maxTotalSize: 1024 * 1024 * 1024 * 2, // 最大缓存 2GBstalePeriod: Duration(days: 7), // 缓存保留时间repo: JsonCacheInfoRepository(databaseName: key),fileSystem: IOFileSystem(key),fileService: HttpFileService(),),);
}

 暴露出来新加的dart类

                3.1.3,在video_widget组件中使用缓存工具缓存视频 

        3.2,在没有网的时候使用该缓存视频,改造步骤2中的播放方法:

_meeduPlayerController.setDataSource(//1网络时候的DataSource// DataSource(//   type: DataSourceType.network,//   source: widget.videoUrl != ""//       ? widget.videoUrl//       : "https://movietrailers.apple.com/movies/paramount/the-spongebob-movie-sponge-on-the-run/the-spongebob-movie-sponge-on-the-run-big-game_h720p.mov",//   httpHeaders: {"Range": "bytes=0-1023"},// ),//2本地文件//错误写法:// DataSource(//   type: DataSourceType.file,//   // file: cacheFile,//   source://       "/data/user/0/com.example.client/cache/customCacheKey/9dade030-3153-11f0-b119-93d21292c9e9.mp4",// ),//正确写法// DataSource(//   type: DataSourceType.file,//   // file: cacheFile,//   file: File(//       "/data/user/0/com.example.client/cache/customCacheKey/9dade030-3153-11f0-b119-93d21292c9e9.mp4"),// ),//所以根据条件判断用上边的任一个dataSourcedataSource,autoplay: !background && widget.autoplay,);

        3.2.1,这个步骤中的插曲,就是使用本地文件一直报空,打印了_meeduPlayerController,和cacheFile都不为空,但是还是报空。

可能得问题有:

一,以为是异步写法awiat获得值,会产生后边的代码先于值计算出来,就运行了导致空

二,错误写法只是照搬了网络视频的写法,更换了一下type的参数,并没有多想,以为也是根据source来写;

解决问题一:

1看下await是怎么产生的。

        1.1,拿本地的缓存文件就有异步

        1.2,判断文件是否完成,是否可播也有await 

2如何避免;如果避免不了await,如何等值完全算完,不为空了再进行下一步的调用。

判断内容长度,是否下载完成,获取sp,判断是否可播都需要异步,就是不能直接拿到值。

Future<int?> getCachedContentLength(String url) async {final prefs = await SharedPreferences.getInstance();return prefs.getInt('video_content_length_$url');}Future<void> cacheContentLength(String url, int length) async {final prefs = await SharedPreferences.getInstance();prefs.setInt('video_content_length_$url', length);}Future<bool> isVideoFileComplete(String url) async {// 获取之前缓存的原始大小final expectedLength = await getCachedContentLength(url);if (expectedLength == null) return false;// 获取本地缓存文件FileInfo? fileInfo = await DefaultCacheManager().getFileFromCache(url);final file = fileInfo?.file;if (file == null || !file.existsSync()) return false;final localLength = file.lengthSync();bool isSame = (localLength == expectedLength);print("video_widget 是否下载完成:$isSame");return isSame;}Future<bool> isVideoPlayable(String filePath) async {final controller = VideoPlayerController.file(File(filePath));try {await controller.initialize();await controller.dispose();print("video_widget 可以 正常播放");return true;} catch (e) {print("video_widget 不能 正常播放");return false;}}

所以用到这几个方法的设置setDataSource()方法也必定是异步的

// 单独封装异步判断逻辑Future<DataSource> _getDataSource(File? cachedFile, String url) async {if (cachedFile != null) {final exists = cachedFile.existsSync();final playable = await isVideoPlayable(cachedFile.path);final complete = await isVideoFileComplete(cachedFile.path);print("video_widget: cachedFile != null: ${cachedFile != null}");print("video_widget: existsSync: $exists");print("video_widget: isVideoPlayable: $playable");print("video_widget: isVideoFileComplete: $complete");if (exists && playable && complete) {print("video_widget:即将使用缓存视频");return DataSource(type: DataSourceType.file,source: cachedFile.path,httpHeaders: {"Range": "bytes=0-1023"},);}}// 如果没有命中缓存或缓存不完整,则走网络加载File? cacheFile;try {cacheFile = await CustomVideoCacheManager.instance.getSingleFile(url);} catch (e) {print("video_widget:网络文件获取失败: $e");}final networkSource = DataSource(type: DataSourceType.network,source: widget.videoUrl.isNotEmpty? widget.videoUrl: "https://movietrailers.apple.com/movies/paramount/the-spongebob-movie-sponge-on-the-run/the-spongebob-movie-sponge-on-the-run-big-game_h720p.mov",httpHeaders: {"Range": "bytes=0-1023"},);return cacheFile != null? DataSource(type: DataSourceType.file,file: cacheFile,): networkSource;}

使用这种方法,就不用在_meeduPlayerController设置参数的时候使用一个异步返回的dataSource了,代码如下,这样就可以使用一个看似同步的代码,完成了一个异步的操作。(并不会因为看起来像是同步的写法,就会发生dataSource的值还没回来的时候就执行了后边的代码,导致null产生。这个就是典型的支持异步操作的代码,不然就得像Java一样写回调了。)

// 封装异步获取 DataSource 的逻辑
dataSource = await _getDataSource(cachedFile, lastUrl);_meeduPlayerController.setDataSource(//所以根据条件判断用上边的任一个dataSourcedataSource,autoplay: !background && widget.autoplay,);

不用特意写then来完成这个异步操作,以下代码不推荐:

await _getDataSource(cachedFile, lastUrl).then((dataSource) {if (dataSource != null) {_meeduPlayerController.setDataSource(dataSource,autoplay: !background && widget.autoplay,);} else {print("video_widget:dataSource为空");}});

解决问题二:

1更换本地缓存文件的地址来写死dataSource参数,还是不行

2想到看下这个依赖包的说明文件是否支持本地文件播放,flutter_meedu_videoplayer example | Flutter package 看到是支持的,

3看依赖包的例子是怎么写的,没有具体写怎么播放本地视频

4看依赖包的源码是怎么使用

4.1,dataSource源码怎么使用的(只是设置参数,没有使用这个参数的逻辑)

4.2,那就找使用这个参数的源码:_meeduPlayerController,有怎么设置本地文件的DataSource方法,最终调整成正确的参数设置方式。

最后,以下是video_widget.dart的完整代码,仅供参考

import 'dart:async';
import 'dart:io';import 'package:audio_session/audio_session.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_meedu_videoplayer/meedu_player.dart';
import 'package:game_lib/common/common_page.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:wakelock_plus/wakelock_plus.dart';class VideoWidget extends StatefulWidget {String videoUrl;Function? onVideoEnd;bool autoplay;Function(MeeduPlayerController)? onInit;Function(PlayerStatus)? onVideoStatusChanged;Function(Duration)? onVideoPositionChanged;bool closeFullscreenOnEnd;BoxFit fit;bool fullscreen;Function(bool)? onBackground;VideoWidget({super.key,required this.videoUrl,this.onVideoEnd,this.onInit,this.autoplay = true,this.fullscreen = true,this.fit = BoxFit.contain,this.onVideoStatusChanged,this.closeFullscreenOnEnd = true,this.onVideoPositionChanged,this.onBackground});@overrideState<VideoWidget> createState() => _VideoWidgetState();
}class _VideoWidgetState extends State<VideoWidget>with WidgetsBindingObserver, RouteAware {late final _meeduPlayerController = MeeduPlayerController(controlsStyle: ControlsStyle.primary,screenManager: const ScreenManager(orientations: [DeviceOrientation.landscapeLeft,]),enabledButtons: EnabledButtons(videoFit: false, muteAndSound: false, fullscreen: widget.fullscreen),fits: [BoxFit.contain],initialFit: widget.fit);StreamSubscription? _playerEventSubs;int lastPosition = 0;String lastUrl = "";bool background = false; // 是否处于后台@overridevoid initState() {WidgetsBinding.instance.addObserver(this);WidgetsBinding.instance.addPostFrameCallback((_) {Future.delayed(const Duration(milliseconds: 500), () {_init();});});widget.onInit?.call(_meeduPlayerController);_meeduPlayerController.onPositionChanged.listen((event) {if (event.inSeconds != lastPosition) {lastPosition = event.inMilliseconds;widget.onVideoPositionChanged?.call(event);//print("onPositionChanged: $event ${event.inSeconds}");}});_playerEventSubs = _meeduPlayerController.onPlayerStatusChanged.listen((PlayerStatus status) async {widget.onVideoStatusChanged?.call(status);print("onPlayerStatusChanged: $status");if (status == PlayerStatus.playing) {WakelockPlus.enable();Future.delayed(const Duration(milliseconds: 100), () {if (widget.fit == BoxFit.contain) {_meeduPlayerController.toggleVideoFit();}});} else {WakelockPlus.disable();final session = await AudioSession.instance;if (await session.setActive(false)) {print("AudioSession setActive abandon");}}if (status == PlayerStatus.completed) {if (widget.closeFullscreenOnEnd &&_meeduPlayerController.fullscreen.value &&Navigator.canPop(context)) {
//            Navigator.pop(context);
//            注释上面代码,播放完后不退出全屏}if (widget.onVideoEnd != null) {widget.onVideoEnd!();}}},);Timer? timer;_meeduPlayerController.onDataStatusChanged.listen((DataStatus status) {if (status == DataStatus.error) {setState(() {_meeduPlayerController.errorText = "";});print("============= video widget onDataStatusChanged: $status videoUrl: ${widget.videoUrl}");if (widget.videoUrl.isNotEmpty) {timer?.cancel();timer = Timer(const Duration(milliseconds: 1), () {setSource();});}}});super.initState();}@overridevoid dispose() {_playerEventSubs?.cancel();_meeduPlayerController.dispose();WidgetsBinding.instance.removeObserver(this);AppRouteObserver().routeObserver.unsubscribe(this);super.dispose();}@overrideFuture<void> didChangeAppLifecycleState(AppLifecycleState state) async {print("video widget didChangeAppLifecycleState: $state");final session = await AudioSession.instance;if (state == AppLifecycleState.resumed) {background = false;widget.onBackground?.call(background);_meeduPlayerController.play();} else if (state == AppLifecycleState.paused) {background = true;widget.onBackground?.call(background);_meeduPlayerController.pause();}}@overridevoid didChangeDependencies() {// TODO: implement didChangeDependenciessuper.didChangeDependencies();AppRouteObserver().routeObserver.subscribe(this, ModalRoute.of(context)!);}@overridevoid didPushNext() {Future.delayed(const Duration(milliseconds: 500), () {if (!_meeduPlayerController.fullscreen.value) {_meeduPlayerController.pause();}});}_init() {print("autoplay: ${widget.autoplay}");setSource();}Future<void> setSource() async {if (widget.videoUrl == lastUrl) {return;}lastUrl = widget.videoUrl;File? cachedFile;DataSource? dataSource;try {print("video_widget:设置视频资源,lastUrl:$lastUrl");FileInfo? fileInfo =await CustomVideoCacheManager.instance.getFileFromCache(lastUrl);cachedFile = fileInfo?.file;print("video_widget:缓存文件地址${cachedFile?.path}");} catch (e) {print("video_widget:未找到缓存视频");}// 封装异步获取 DataSource 的逻辑dataSource = await _getDataSource(cachedFile, lastUrl);// await _getDataSource(cachedFile, lastUrl).then((dataSource) {//   print(//       "=====video_widget:_meeduPlayerController是否为空:${_meeduPlayerController == null}");//   print("=====video_widget:dataSource是否为空:${dataSource == null}");//   if (dataSource != null) {//     _meeduPlayerController.setDataSource(//       // DataSource(//       //   type: DataSourceType.network,//       //   source: widget.videoUrl != ""//       //       ? widget.videoUrl//       //       : "https://movietrailers.apple.com/movies/paramount/the-spongebob-movie-sponge-on-the-run/the-spongebob-movie-sponge-on-the-run-big-game_h720p.mov",//       //   httpHeaders: {"Range": "bytes=0-1023"},//       // ),////       dataSource,////       autoplay: !background && widget.autoplay,//     );//   } else {//     print("video_widget:dataSource为空");//   }// });//清除缓存//await CustomVideoCacheManager.instance.emptyCache();_meeduPlayerController.setDataSource(// DataSource(//   type: DataSourceType.network,//   source: widget.videoUrl != ""//       ? widget.videoUrl//       : "https://movietrailers.apple.com/movies/paramount/the-spongebob-movie-sponge-on-the-run/the-spongebob-movie-sponge-on-the-run-big-game_h720p.mov",//   httpHeaders: {"Range": "bytes=0-1023"},// ),// DataSource(//   type: DataSourceType.file,//   // file: cacheFile,//   file: File(//       "/data/user/0/com.example.client/cache/customCacheKey/9dade030-3153-11f0-b119-93d21292c9e9.mp4"),// ),dataSource,autoplay: !background && widget.autoplay,);}// 单独封装异步判断逻辑Future<DataSource> _getDataSource(File? cachedFile, String url) async {if (cachedFile != null) {final exists = cachedFile.existsSync();final playable = await isVideoPlayable(cachedFile.path);final complete = await isVideoFileComplete(cachedFile.path);print("video_widget: cachedFile != null: ${cachedFile != null}");print("video_widget: existsSync: $exists");print("video_widget: isVideoPlayable: $playable");print("video_widget: isVideoFileComplete: $complete");if (exists && playable && complete) {print("video_widget:即将使用缓存视频");return DataSource(type: DataSourceType.file,source: cachedFile.path,httpHeaders: {"Range": "bytes=0-1023"},);}}// 如果没有命中缓存或缓存不完整,则走网络加载File? cacheFile;try {cacheFile = await CustomVideoCacheManager.instance.getSingleFile(url);} catch (e) {print("video_widget:网络文件获取失败: $e");}final networkSource = DataSource(type: DataSourceType.network,source: widget.videoUrl.isNotEmpty? widget.videoUrl: "https://movietrailers.apple.com/movies/paramount/the-spongebob-movie-sponge-on-the-run/the-spongebob-movie-sponge-on-the-run-big-game_h720p.mov",httpHeaders: {"Range": "bytes=0-1023"},);return cacheFile != null? DataSource(type: DataSourceType.file,file: cacheFile,): networkSource;}Future<int?> getCachedContentLength(String url) async {final prefs = await SharedPreferences.getInstance();return prefs.getInt('video_content_length_$url');}Future<void> cacheContentLength(String url, int length) async {final prefs = await SharedPreferences.getInstance();prefs.setInt('video_content_length_$url', length);}Future<bool> isVideoFileComplete(String url) async {// 获取之前缓存的原始大小final expectedLength = await getCachedContentLength(url);if (expectedLength == null) return false;// 获取本地缓存文件FileInfo? fileInfo = await DefaultCacheManager().getFileFromCache(url);final file = fileInfo?.file;if (file == null || !file.existsSync()) return false;final localLength = file.lengthSync();bool isSame = (localLength == expectedLength);print("video_widget 是否下载完成:$isSame");return isSame;}Future<bool> isVideoPlayable(String filePath) async {final controller = VideoPlayerController.file(File(filePath));try {await controller.initialize();await controller.dispose();print("video_widget 可以 正常播放");return true;} catch (e) {print("video_widget 不能 正常播放");return false;}}@overrideWidget build(BuildContext context) {setSource();return AspectRatio(aspectRatio: 16 / 9,child: MeeduVideoPlayer(key: UniqueKey(),controller: _meeduPlayerController,),);}
}

相关文章:

flutter缓存网络视频到本地,可离线观看

记录一下解决问题的过程&#xff0c;希望自己以后可以参考看看&#xff0c;解决更多的问题。 需求&#xff1a;flutter 缓存网络视频文件&#xff0c;可离线观看。 解决&#xff1a; 1&#xff0c;flutter APP视频播放组件调整&#xff1b; 2&#xff0c;找到视频播放组件&a…...

2025年Ai写PPT工具推荐,这5款Ai工具可以一键生成专业PPT

上个月给客户做产品宣讲时&#xff0c;我对着空白 PPT 页面熬到凌晨一点&#xff0c;光是调整文字排版就改了十几版&#xff0c;最后还是被吐槽 "内容零散没重点"。后来同事分享了几款 ai 写 PPT 工具&#xff0c;试完发现简直打开了新世界的大门 —— 不用手动写大纲…...

【深度学习】#11 优化算法

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 深度学习中的优化挑战局部极小值鞍点梯度消失 凸性凸集凸函数 梯度下降一维梯度下降学习率局部极小值 多元梯度下降 随机梯度下降随机梯度更新动态学习率…...

数学复习笔记 13

前言 继续做线性相关的练习题&#xff0c;然后做矩阵的例题&#xff0c;还有矩阵的练习题。 646 A 明显是错的。因为假设系数全部是零&#xff0c;就不是线性相关了。要限制系数不全是零&#xff0c;才可以是线性相关。 B 这个说法好像没啥问题。系数全为零肯定线性组合的结…...

AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年5月16日第79弹

从今天开始&#xff0c;咱们还是暂时基于旧的模型进行预测&#xff0c;好了&#xff0c;废话不多说&#xff0c;按照老办法&#xff0c;重点8-9码定位&#xff0c;配合三胆下1或下2&#xff0c;杀1-2个和尾&#xff0c;再杀6-8个和值&#xff0c;可以做到100-300注左右。 (1)定…...

阳台光伏+储能:安科瑞智能计量仪表来助力

随着可再生能源的普及和家庭储能需求的增长&#xff0c;阳台光伏储能系统逐渐成为家庭能源管理的新趋势。如何精准计量储能系统的发电量、用电量及电网交互数据&#xff0c;成为优化能源利用效率的关键。安科瑞计量仪表凭借高精度、多功能及智能化特性&#xff0c;为家庭阳台储…...

Unable to determine the device handle for GPU 0000:1A:00.0: Unknown Error

Unable to determine the device handle for GPU 0000:1A:00.0: Unknown Error 省流&#xff1a;我遇到这个问题重置bios设置就好了 这个错误信息表明系统无法识别或访问GPU&#xff08;0000:1A:00.0&#xff09;&#xff0c;通常与CUDA、驱动程序或硬件相关。以下是可能的原…...

多态性标记设计

1.确定区间 2.获取该区间内的序列&#xff0c;如果只有一个位置&#xff0c;可以前后扩100bp 使用ncbi primer blast进行引物设计&#xff08;https://blast.ncbi.nlm.nih.gov/Blast.cgi&#xff09;...

Jenkins 最佳实践

1. 在Jenkins中避免调度过载 过载Jenkins以同时运行多个作业可能导致资源竞争、构建速度变慢和系统性能问题。分配作业启动时间可以防止瓶颈&#xff0c;并确保更顺畅的执行。如何实现&#xff1f; 在Cron表达式中使用H&#xff1a;引入抖动&#xff08;jitter&#xff09;&a…...

如何查询Ubuntu系统中最大的几个目录以G单位显示大小,从大到小排列?

环境&#xff1a; Ubuntu 20,04 问题描述&#xff1a; 如何查询系统中最大的几个目录以G单位显示大小&#xff0c;从大到小排列&#xff1f; 解决方案&#xff1a; 想查看整个系统&#xff08;单一文件系统内&#xff09;最大的20个目录&#xff0c;结果按大小从大到小排序…...

深入浅出拆分学习,图神经网络拆分学习,混合联邦学习

深入浅出解析拆分学习&#xff08;Split Learning&#xff09;、图神经网络拆分学习&#xff08;Split Learning for Graph Neural Networks&#xff09;以及混合联邦学习&#xff08;Hybrid Federated Learning&#xff09;&#xff0c;这三者都体现了在分布式数据环境下进行机…...

DDD领域驱动介绍

&#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》&#xff08;基础篇&#xff09;、&#xff08;进阶篇&#xff09;、&#xff08;架构篇&#xff09;清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、…...

ubuntu22鼠键失灵恢复记录笔记chatgpt解决

ChatGPT 说&#xff1a; 你提到“Ubuntu 22 鼠键失灵”&#xff0c;这个问题可能涉及以下几方面&#xff1a; &#x1f9ed; 先确认问题 是鼠标问题还是键盘问题&#xff0c;还是触控板&#xff1f; “鼠键”一般理解为“鼠标键”&#xff0c;请确认你是指鼠标左键/右键失灵&a…...

在服务器上安装AlphaFold2遇到的问题(1)

犯了错误&#xff0c;轻信deepseek&#xff0c;误将cuDNN8.9.7删掉 [rootlocalhost ~]# cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2 #define CUDNN_MAJOR 8 #define CUDNN_MINOR 9 #define CUDNN_PATCHLEVEL 7 -- #define CUDNN_VERSION (CUDNN_MA…...

ch10 题目参考思路

ch10 - 最小生成树 有线通讯网 知识点&#xff1a;Prim 算法思路&#xff1a; 该题要求对 n 座城市铺设 n - 1 条光缆&#xff0c;并要求所有城市连通&#xff0c;那本质上是一棵树&#xff0c;又要求铺设光缆的费用最低&#xff0c;即要求选取的 n - 1 条光缆的长度最小&…...

Hudi、Iceberg 、 Paimon 数据湖选型对比

Hudi、Iceberg 和 Paimon 是当前数据湖领域的三大主流开源框架,均致力于解决数据湖场景下的增量更新、事务支持、元数据管理、流批统一等核心问题,但设计理念和适用场景存在差异。以下从技术特性、适用场景和选型建议三方面对比分析: 一、核心技术特性对比 维度HudiIceberg…...

2025认证杯数学建模第二阶段A题完整论文(代码齐全):小行星轨迹预测思路

2025认证杯数学建模第二阶段A题完整论文&#xff08;代码齐全&#xff09;:小行星轨迹预测思路,详细内容见文末名片 第二阶段问题 1 分析 问题起源与相关性&#xff1a;为了更全面地评估近地小行星对地球的潜在威胁&#xff0c;需要对其轨道进行长期预测。三个月内的观测数据为…...

信息安全基础知识

信息系统 信息系统能进行&#xff08;数据&#xff09;的采集、传输、存储、加工&#xff0c;使用和维护的计算机应用系统 例如&#xff1a;办公自动化、CRM/ERP、HRM、12306火车订票系统等。 信息安全 信息安全是指保护信息系统中的计算机硬件、软件、数据不因偶然或者恶意…...

UE RPG游戏开发练手 第二十六课 普通攻击1

UE RPG游戏开发练手 第二十六课 普通攻击1 1.定义攻击的InputTag MyGameplayTags.h代码 RPGGAMETEST_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_LightAttack_Axe);MyGameplayTag.cpp代码 UE_DEFINE_GAMEPLAY_TAG(InputTag_LightAttack_Axe, "InputTag.LightAttack.Ax…...

SAP ABAP 程序中归档数据读取方式

上一篇文章记录了字段目录&#xff0c;归档信息结构&#xff0c;这篇文章记录如何通过字段目录&#xff0c;归档信息结构&#xff0c;归档对象读取归档数据。未归档数据是从数据库表直接抽取&#xff0c;本样例是通过归档读取方式复写sql。 发布时间&#xff1a;2025.05.16 示…...

每周资讯 | 腾讯Q1财报:国内游戏业务收入同比增长24%;Tripledot 8亿美元收购AppLovin游戏业务

内容速览&#xff1a; 广州“服务贸易和数字贸易22条”助推游戏产业发展Tripledot Studios 8亿美元收购AppLovin游戏业务苹果紧急申请暂停执行AppStore新规4月中国手游出海收入下载榜&#xff0c;点点互动《Kingshot》收入激增 腾讯Q1财报&#xff1a;国内游戏业务收入同比增长…...

iOS SwiftUI的具体运用实例(SwiftUI库的运用)

最近接触到一个 SwiftUI的第三方框架&#xff0c;它非常的好用。以下是 具体运用实例&#xff0c;结合其核心功能与开发场景&#xff0c;分多个维度进行详细解析&#xff1a; 一、基础 UI 组件开发 登录界面 SwiftUI 的 VStack、TextField 和 Button 可快速构建用户登录表单。例…...

杰理ac696配置sd卡随机播放

#define FCYCLE_LIST 0 // 列表循环&#xff08;按顺序播放文件列表&#xff09; #define FCYCLE_ALL 1 // 全部循环&#xff08;播放完所有文件后重新开始&#xff09; #define FCYCLE_ONE 2 // 单曲循环&#xff08;重复播放当前文件&#xff09; #define …...

MCP协议的核心机制和交互过程

MCP的核心是JSON-RPC 2.0 MCP使用了 JSON-RPC 2.0 作为client和server端的消息传输。JSON-RPC 2.0是一个用JSON编码的轻量级远程过程调用协议。它的优越性如下: 易读,易调试与编程语言无关,环境无关技术成熟,规范清晰且应用广泛JSON-NPC 2.0定义了request、response、noti…...

论信息系统项目的范围管理

论信息系统项目的范围管理 前言一、规划范围管理&#xff0c;收集需求二、定义范围三、创建工作分解结构四、确认范围五、控制范围 前言 为了应对烟草零售客户数量大幅度增长所带来的问题&#xff0c;切实履行控烟履约的相关要求&#xff0c;同时也为了响应国务院“放管服”政策…...

米勒电容补偿的理解

米勒电容补偿是使运放放大器稳定的重要手法&#xff0c;可以使两级运放的两个极点分离&#xff0c;从而可以得到更好的相位裕度。 Miller 电容补偿的本质是增加一条通路流电流&#xff0c;流电流才是miller效应的本质。给定一个相同的输入&#xff0c;Miller 电容吃掉的电流比…...

力扣654题:最大二叉树(递归)

小学生一枚&#xff0c;自学信奥中&#xff0c;没参加培训机构&#xff0c;所以命名不规范、代码不优美是在所难免的&#xff0c;欢迎指正。 标签&#xff1a; 二叉树、递归 语言&#xff1a; C 题目&#xff1a; 给定一个不重复的整数数组 nums 。最大二叉树可以用下面的算…...

Go语言实现生产者-消费者问题的多种方法

Go语言实现生产者-消费者问题的多种方法 生产者-消费者问题是并发编程中的经典问题&#xff0c;涉及多个生产者生成数据&#xff0c;多个消费者消费数据&#xff0c;二者通过缓冲区&#xff08;队列&#xff09;进行协调&#xff0c;保证数据的正确传递和同步。本文将从简单到…...

深度学习驱动下的目标检测技术:原理、算法与应用创新(二)

三、主流深度学习目标检测算法剖析 3.1 R - CNN 系列算法 3.1.1 R - CNN 算法详解 R - CNN&#xff08;Region - based Convolutional Neural Networks&#xff09;是将卷积神经网络&#xff08;CNN&#xff09;应用于目标检测领域的开创性算法&#xff0c;其在目标检测发展历…...

提权脚本Powerup命令备忘单

1. 获取与加载 从 GitHub 下载&#xff1a;(New-Object Net.WebClient).DownloadFile("https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Privesc/PowerUp.ps1", "C:\Temp\PowerUp.ps1")本地加载&#xff1a;Import-Module .\Power…...

人工智能 (AI) 在无线接入网络 (RAN) 中的变革性作用

随着电信行业向更智能、更高效的系统迈进&#xff0c;将 AI 集成到 RAN 中已不再是可有可无&#xff0c;而是至关重要。 随着 6G 时代的到来&#xff0c;人工智能 (AI) 有望降低运营成本&#xff0c;并带来更大的盈利机会。AI-RAN 正处于这一变革的前沿&#xff0c;在 RAN 环境…...

从硬件角度理解“Linux下一切皆文件“,详解用户级缓冲区

目录 前言 一、从硬件角度理解"Linux下一切皆文件" 从理解硬件是种“文件”到其他系统资源的抽象 二、缓冲区 1.缓冲区介绍 2.缓冲区的刷新策略 3.用户级缓冲区 这个用户级缓冲区在哪呢&#xff1f; 解释关于fork再加重定向“>”后数据会打印两份的原因 4.内核缓冲…...

Python-感知机以及实现感知机

感知机定义 如果有一个算法&#xff0c;具有1个或者多个入参&#xff0c;但是返回值要么是0&#xff0c;要么是1&#xff0c;那么这个算法就叫做感知机&#xff0c;也就是说&#xff0c;感知机是个算法 感知机有什么用 感知机是用来表示可能性的大小的&#xff0c;我们可以认…...

根据台账批量制作个人表

1. 前期材料准备 1&#xff09;要有 人员总的信息台账 2&#xff09;要有 个人明白卡模板 2. 开始操作 1&#xff09;打开 人员总的信息台账&#xff0c;选择所需要的数据模块&#xff1b; 2&#xff09;点击插入&#xff0c;选择数据透视表&#xff0c;按流程操作&…...

ohttps开启群晖ssl证书自动更新

开启群晖ssl证书自动更新OHTTPS ohttps是一个免费自动签发ssl证书、管理、部署的项目。 https://ohttps.com 本文举例以ohttps项目自动部署、更新群晖的ssl证书。 部署 签发证书 打开ohttps-证书管理-创建证书-按你实际情况创建证书。创建部署节点 打开Ohttps-部署节点-添加…...

【Elasticsearch】flattened`类型在查询嵌套数组时可能返回不准确结果的情况

好的&#xff01;为了更清楚地说明flattened类型在查询嵌套数组时可能返回不准确结果的情况&#xff0c;我们可以通过一个具体的例子来展示。这个例子将展示如何在文档中没有完全匹配的嵌套对象时&#xff0c;flattened类型仍然可能返回该文档。 示例文档结构 假设你有以下文…...

【知识点】语义分割任务中有哪些损失函数?

在语义分割任务中,模型需要对图像中的每个像素进行分类。因此,损失函数的设计不仅要关注整体精度,还需要特别注意目标物体的边界区域。以下是一些常用的损失函数及其适用场景,包括数学公式、PyTorch 实现和是否适合处理边界问题。 📌 一、交叉熵损失 Cross-Entropy Loss …...

Node.js 同步加载问题详解:原理、危害与优化策略

文章目录 一、什么是同步加载&#xff1f;二、同步加载的危害场景三、检测同步加载问题四、解决方案与代码优化 一、什么是同步加载&#xff1f; 1.核心概念 在 Node.js 的 CommonJS 模块系统中&#xff0c;require() 是同步操作&#xff1a; // 模块加载会阻塞后续代码执行 …...

linux下tcp/ip网络通信笔记1,

本文章主要为博主在学习网络通信的笔记一个Udp_echo_server,和client的代码实现 1&#xff0c;网络发展&#xff0c;网络协议&#xff0c;意识到网络通信——不同主机的进程间通信&#xff0c; 2&#xff0c;学习如何在应用层调用系统提供的接口进行通信&#xff0c;echo_Udp…...

网络攻防模拟:城市安全 “数字预演”

在当今数字化快速发展的时代&#xff0c;网络安全和城市安全面临着前所未有的挑战。为有效应对这些挑战&#xff0c;利用先进的技术搭建模拟演练平台至关重要。图扑软件的 HT for Web 技术&#xff0c;为网络攻防模拟与城市安全演练提供了全面且高效的解决方案。 三维场景搭建&…...

在 Ubuntu 20.04 中使用 init.d 或者systemd实现开机自动执行脚本

Ubuntu 20 默认使用的是 systemd 系统管理器&#xff0c;但传统的 SysV Init&#xff08;/etc/init.d/&#xff09;脚本依然兼容并可用。本文将介绍如何通过 init.d 写脚本来在开机时自动设置某个 GPIO&#xff08;如 GPIO407&#xff09;为高电平&#xff0c;适用于嵌入式系统…...

2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛) 解题报告 | 珂学家

前言 题解 2024 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛)。 国赛比省赛难一些&#xff0c;做得汗流浃背&#xff0c;T_T. RC-u1 大家一起查作弊 分值: 15分 这题真的太有意思&#xff0c;看看描述 在今年的睿抗比赛上&#xff0c;有同学的提交代码如下&#xff1…...

【生成式AI文本生成实战】从GPT原理到企业级应用开发

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1fa79; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f9e0; 一、技术原理剖析&#x1f4ca; 核心概念图解&#x1f4a1; 核心作用讲解&#x1f527; 关键技术模块说明⚖️ 技术选…...

【目标检测】RT-DETR

DETRs Beat YOLOs on Real-time Object Detection DETR在实时目标检测任务中超越YOLO CVPR 2024 代码地址 论文地址 0.论文摘要 YOLO系列因其在速度与精度间的均衡权衡&#xff0c;已成为实时目标检测领域最受欢迎的框架。然而我们观察到&#xff0c;非极大值抑制&#xf…...

数据库行业竞争加剧,MySQL 9.3.0 企业版开始支持个人下载

最新发现&#xff0c;Oracle 官方网站放开了 MySQL 9.3.0 企业版下载链接&#xff0c;个人用户也可以免费下载&#xff0c;不过只能用于学习、开发或者原型测试&#xff0c;不能用于生产环境。 通常我们都是下载 MySQL 社区版&#xff0c;不过 MySQL 企业版可以支持更多高级功能…...

QMK宏全面实战教程:从入门到精通(附17个实用案例)(理论部分)

🎯 QMK宏全面实战教程:从入门到精通(附17个实用案例) 大家好!作为一名机械键盘DIY爱好者和QMK固件深度玩家,今天我要带大家彻底掌握QMK宏的使用技巧!无论你是刚接触机械键盘的新手,还是想提升定制化水平的老玩家,这篇包含17个实战案例的教程都能满足你的需求! 🔍…...

H3C网络设备(交换机、路由器、防火墙)常用命令整理

H3C网络设备&#xff08;交换机、路由器、防火墙&#xff09;的常用命令整理。 一、H3C交换机常用命令 1. 基础操作 命令说明system-view进入系统视图quit返回上一级视图save保存配置display current-configuration查看当前配置&#xff08;类似 show run&#xff09;display…...

从前序与中序遍历序列构造二叉树(中等)

先从前序遍历列表取出第一个元素&#xff0c;这个元素就是根节点&#xff0c;然后从中序遍历中找到这个根节点&#xff0c;节点左侧就是该节点的左子树的节点集合&#xff0c;右侧就是该节点的右侧节点集合&#xff0c;然后递归构建左右子树。 /*** Definition for a binary t…...

ASP.NET/IIS New StreamContent(context.Request.InputStream) 不会立即复制整个请求流的内容到内存

StreamContent 的工作原理与内存占用 New StreamContent(context.Request.InputStream) 不会立即复制整个请求流的内容到内存。这个操作只是创建一个包装器&#xff0c;将原始的请求流&#xff08;context.Request.InputStream&#xff09;封装在 StreamContent 对象中&#x…...

Java大师成长计划之第24天:Spring生态与微服务架构之分布式配置与API网关

&#x1f4e2; 友情提示&#xff1a; 本文由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;平台gpt-4-turbo模型辅助创作完成&#xff0c;旨在提供灵感参考与技术分享&#xff0c;文中关键数据、代码与结论建议通过官方渠道验证。 在微服务架构中&#xff0c;如何管理…...