“UniApp的音频播放——点击视频进入空白+解决视频播放器切换视频时一直加载的问题”——video.js、video-js.css

       今天,又解决了一个单子“UniApp的音频播放——点击视频进入空白+解决视频播放器切换视频时一直加载的问题”


一、问题描述

在开发一个基于 video.js 的视频播放器时,用户通过上下滑动切换视频时,视频一直处于加载状态,无法正常播放。通过日志可以看到,视频源地址和索引更新是正确的,但视频无法播放。具体表现为:

  1. 视频加载卡住:切换视频时,播放器一直显示加载动画,无法播放视频。

  2. 日志显示正常:日志中显示的视频源地址和索引更新是正确的,例如:

    即将更新视频源为: http://127.0.0.1:8000/media/m3u8/30bd5d2225919b1724ca69d07633beb1/index.m3u8
    currentIndex: 1
    videos长度: 4
  3. 播放器未正确响应:尽管视频源地址更新了,但播放器未能正确加载和播放新视频。


 二、问题复现步骤

  1. 初始化播放器:加载第一个视频,播放器正常工作。

  2. 滑动切换视频:用户通过上下滑动切换到下一个视频。

  3. 视频加载卡住:播放器显示加载动画,但视频无法播放。

  4. 日志输出:日志显示视频源地址和索引更新正确,但播放器未响应。


    三、来请看代码,各位客官

<template><!-- <view@click="handleVideoClick"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd"> --><!--  根据 isAdVideo 的值决定显示广告视频还是常规视频 --><!-- 对于广告视频,不显示控制条,自动播放 --><!-- <video v-if="isAdVideo" :src="videoSrc" :controls="false" autoplay></video> --><!-- 对于常规视频,显示控制条,自动播放 --><!-- <video v-else :src="videoSrc" controls autoplay></video> --><!-- </view> -->
<view><div id="app"><div class="video-js" ref="videos"></div></div>
</view>
</template><script>import { baseUrl } from '@/common/api.js'
export default {data() {return {// 存储当前视频文件的路径videoSrc: '',// 标记当前视频是否为广告视频isAdVideo: false,// 存储广告的 URLadUrl: '',// 存储当前视频在视频列表中的索引currentIndex: 0,// 存储所有视频的数组videos: [],// 存储触摸开始时的 Y 坐标touchStartY: 0,// 存储触摸结束时的 Y 坐标touchEndY: 0,// video.js 的播放器实例player: null,};},onLoad(options) {// 从传入的参数中获取视频文件路径const videoFile = options.videoFile;// 判断是否为广告视频,将字符串 'true' 转换为布尔值const isAd = options.isAd === 'true';// 从传入的参数中获取广告 URL,并进行解码const adUrl = options.adUrl? decodeURIComponent(options.adUrl) : '';// 从传入的参数中获取视频列表,并将其从 JSON 字符串转换为数组const videos = options.videos? JSON.parse(decodeURIComponent(options.videos)) : [];// 将视频文件路径存储到 data 中,修改错误点 1// this.videoFile = videoFile;// 将是否为广告视频的状态存储到 data 中this.isAdVideo = isAd;// 将广告 URL 存储到 data 中this.adUrl = adUrl;// 将视频列表存储到 data 中this.videos = videos;// 根据是否为广告视频来确定视频源的路径if (isAd) {// 假设广告视频的文件名直接作为参数传递,提取文件名const adVideoPath = `${videoFile}`;console.log('1111',adVideoPath);// 拼接完整的广告视频源路径this.videoSrc = `${baseUrl}${adVideoPath}`;} else {// 对于常规视频,在视频列表中查找匹配的视频文件const video = videos.find(v => {console.log('当前视频的 m3u8_url:', v.m3u8_url);  // 打印每个视频的 m3u8_urlreturn v.m3u8_url === videoFile;});console.log('222',videoFile);// const video = videos.find(v => v.m3u8_url === videoFile);// console.log('222',v =>v.m3u8_url,videoFile);if (video) {// 拼接完整的常规视频源路径this.videoSrc = `${baseUrl}${video.m3u8_url}`;} else {// 如果未找到对应的视频文件,打印错误信息并退出方法console.error('未找到对应的视频文件路径');return;}}// 查找当前视频在视频列表中的索引this.currentIndex = this.videos.findIndex(v => {if (this.isAdVideo) {const asa =v.ad && v.ad.m3u8_url === videoFile;// 对于广告视频,通过广告视频文件查找索引console.log('当前视频的 vad:', v.ad.m3u8_url,asa);console.log('videoFile',videoFile)return asa ;}// 对于常规视频,通过常规视频文件查找索引return v.m3u8_url === videoFile;});console.log('this.videoFile',videos.find(v => v.m3u8_url === videoFile).m3u8_url);// 打印初始的视频文件路径console.log('Initial video file:', this.videoSrc);},
// beforeDestroy() {
// 	var playerElement = document.getElementById('video');
// 	var player = videojs.getInstance(playerElement);
// 	if (player) {
// 	 player.dispose();
// 	 } // },mounted() {this.initplayer();},beforeDestroy() {// 使用 $refs 来查找 video 元素const videoElement = this.$refs.videos.querySelector('video');if (videoElement) {const player = videojs.getPlayer(videoElement);if (player) {console.log('播放器正在销毁');player.dispose();} else {console.log('未找到播放器实例,可能未初始化');}} else {console.log('未找到 video 元素');}},methods: {initplayer(){// const videoElement = this.$refs.videos.querySelector('video');// const player = videojs.getPlayer(videoElement);// player.dispose();// if (this.player) {//         // 如果播放器已经初始化,直接设置新的视频源//         this.player.src({ src: this.videoSrc, type: 'application/x-mpegURL' });//         this.player.play();//         return;//       }let video = document.createElement('video');video.id = 'video';// video.style = 'width: 100%; height: 100%;';// video.controls = true;video.preload = "auto"video.setAttribute('playsinline', true) //IOS微信浏览器支持小窗内播放video.setAttribute('webkit-playsinline', true) //这个bai属性是ios 10中设置可以让视频在小du窗内播放,也就是不是全zhi屏播放的video标签的一个属性video.setAttribute('x5-video-player-type', 'h5') //安卓 声明启用同层H5播放器 可以在video上面加东西// const ada='http://127.0.0.1:8000/media\\m3u8\\caba10d1b61e5f2aa1e068bebeb55663\\index.m3u8';let source = document.createElement('source');// source.src = ada;source.src = this.videoSrc;video.appendChild(source);// returnthis.$refs.videos.appendChild(video);let that = this;let player = this.$video('video', {autoDisable: true,preload: 'none', //auto - 当页面加载后载入整个视频 meta - 当页面加载后只载入元数据 none - 当页面加载后不载入视频language: 'zh-CN',fluid: true, // 自适应宽高muted: false, //  是否静音aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")controls: true, //是否拥有控制条 【默认true】,如果设为false ,那么只能通过api进行控制了。也就是说界面上不会出现任何控制按钮autoplay: false, //如果true,浏览器准备好时开始回放。 autoplay: "muted", // //自动播放属性,muted:静音播放loop: true, // 导致视频一结束就重新开始。 视频播放结束后,是否循环播放controlBar: {volumePanel: { //声音样式inline: true // 不使用水平方式},timeDivider: true, // 时间分割线durationDisplay: true, // 总时间progressControl: true, // 进度条remainingTimeDisplay: true, //当前以播放时间fullscreenToggle: true, //全屏按钮pictureInPictureToggle: false, //画中画}}, function() {this.on('error', function(err) { //请求数据时遇到错误console.log("请求数据时遇到错误", err)});this.on('stalled', function(stalled) { //网速失速console.log("网速失速", stalled)});});},// 处理触摸开始事件,记录触摸开始时的 Y 坐标handleTouchStart(event) {this.touchStartY = event.touches[0].clientY;},// 处理触摸移动事件,目前不做任何处理,可添加优化逻辑handleTouchMove(event) {// 例如,可以添加代码防止快速滑动时的抖动效果},// 处理触摸结束事件,记录触摸结束时的 Y 坐标,并调用 handleSwipe 方法handleTouchEnd(event) {this.touchEndY = event.changedTouches[0].clientY;this.handleSwipe();},// 处理滑动操作handleSwipe() {// 计算触摸的垂直距离const distance = this.touchEndY - this.touchStartY;// 如果滑动距离小于 30 像素,不进行任何操作if (Math.abs(distance) < 30) {return;}// 如果滑动距离大于 0,表示向下滑动,调用 handleSwipeDown 方法if (distance > 0) {this.handleSwipeDown();} else {// 否则表示向上滑动,调用 handleSwipeUp 方法this.handleSwipeUp();}},// 处理向上滑动,切换到下一个视频handleSwipeUp() {// 如果不是最后一个视频if (this.currentIndex < this.videos.length - 1) {// 增加当前视频索引this.currentIndex++;// 更新视频信息this.updateVideo();// 打印下一个视频的文件路径console.log('Swipe Up: Next video file:', this.videoSrc);// 打印是否为广告视频console.log('是否广告', this.isAdVideo);} else {// 已到达最后一个视频,打印提示信息console.log("已经是最后一个视频了");}},// 处理向下滑动,切换到上一个视频handleSwipeDown() {// 如果不是第一个视频if (this.currentIndex > 0) {// 减小当前视频索引this.currentIndex--;// 更新视频信息this.updateVideo();// 打印上一个视频的文件路径console.log('Swipe Down: Previous video file:', this.videoSrc);} else {// 已到达第一个视频,打印提示信息console.log("已经是第一个视频了");}},// 更新视频信息,包括视频源和广告 URLupdateVideo() {// 获取当前索引对应的下一个视频const nextVideo = this.videos[this.currentIndex];console.log('11111', this.videos, nextVideo, this.currentIndex);// 判断下一个视频是否为广告视频this.isAdVideo =!!nextVideo.ad;if (this.isAdVideo) {// 如果是广告视频,更新视频源为广告视频源并打印console.log('1111:', nextVideo.ad.m3u8_url);this.videoSrc = `${baseUrl}${nextVideo.ad.m3u8_url}`;} else {// 如果是常规视频,更新视频源为常规视频源并打印this.videoSrc = `${baseUrl}${nextVideo.m3u8_url}`;console.log('2222:', nextVideo.m3u8_url);}// 根据是否为广告视频更新广告 URL,修改错误点 3if (this.isAdVideo) {this.adUrl = nextVideo.ad.urll;} else {this.adUrl = '';}// 当视频源更新时,更新播放器的 srcif (this.player) {this.player.src({ src: this.videoSrc });}},// 处理视频点击事件handleVideoClick() {// 如果是广告视频且有广告 URLif (this.isAdVideo && this.adUrl) {// 根据不同的平台,使用不同的跳转方式打开广告 URLif (process.env.VUE_APP_PLATFORM === 'h5') {// 在 H5 平台使用 window.open 打开广告 URLwindow.open(this.adUrl, '_blank');} else {// 在小程序或其他平台使用 uni.navigateTo 进行跳转uni.navigateTo({url: `/pages/webview/webview?url=${encodeURIComponent(this.adUrl)}`});}}}}
};
</script>

三、可能的原因

  1. 视频源路径格式问题

    • 视频路径中使用了反斜杠 \,例如:http://127.0.0.1:8000\media\m3u8\30bd5d2225919b1724ca69d07633beb1\index.m3u8

    • 反斜杠在某些环境下可能导致路径解析错误。

  2. 播放器未正确销毁和重新初始化

    • 在切换视频时,旧的播放器实例可能未正确销毁,导致新的播放器实例无法正常初始化。

  3. 视频加载超时或失败

    • 视频文件可能无法加载,或者加载时间过长,导致播放器一直处于加载状态。

  4. 用户交互限制

    • 某些浏览器要求视频播放必须在用户交互后触发,如果未正确处理用户交互,可能导致视频无法播放。

  5. 播放器初始化问题

    • 播放器初始化逻辑中,this.$video 未定义,可能导致播放器无法正确初始化。

  6. 广告视频逻辑问题

    • 广告视频的逻辑中,nextVideo.ad.urll 拼写错误,导致广告 URL 无法正确更新。


 四、问题分析

1. 视频路径格式问题

  • 问题:视频路径中使用了反斜杠 \,例如:http://127.0.0.1:8000\media\m3u8\30bd5d2225919b1724ca69d07633beb1\index.m3u8

  • 影响:在某些环境下,反斜杠可能导致路径解析错误,视频无法加载。

  • 解决方案:将反斜杠替换为正斜杠 /

this.videoSrc = `${baseUrl}${videoFile}`.replace(/\\/g, '/');

2. 播放器未正确销毁和重新初始化

  • 问题:在切换视频时,旧的播放器实例可能未正确销毁,导致新的播放器实例无法正常初始化。

  • 影响:切换视频时,播放器可能卡在加载状态或无法播放。

  • 解决方案:在切换视频时,销毁旧的播放器实例并重新初始化新的播放器实例。

updateVideo() {const nextVideo = this.videos[this.currentIndex];this.isAdVideo = !!nextVideo.ad;if (this.isAdVideo) {this.videoSrc = `${baseUrl}${nextVideo.ad.m3u8_url}`.replace(/\\/g, '/');} else {this.videoSrc = `${baseUrl}${nextVideo.m3u8_url}`.replace(/\\/g, '/');}this.adUrl = this.isAdVideo ? nextVideo.ad.url : '';console.log('即将更新视频源为:', this.videoSrc);this.destroyPlayer(); // 销毁旧的播放器实例this.$nextTick(() => {this.initplayer(); // 重新初始化播放器});
}

3. 视频加载超时或失败

  • 问题:视频文件可能无法加载,或者加载时间过长,导致播放器一直处于加载状态。

  • 影响:用户可能会看到视频一直加载,无法播放。

  • 解决方案:设置超时机制,防止长时间停留在加载状态。

    async updateVideoSource() {if (!this.player) return;console.log('正在更新视频源:', this.videoSrc);try {this.player.pause(); // 暂停当前播放this.player.src({ src: this.videoSrc, type: 'application/x-mpegURL' });this.player.load();// 监听 loadeddata 事件,确保视频数据加载完成后再尝试播放this.player.one('loadeddata', () => {console.log('视频数据加载完成');this.isPlaying = false;this.player.play().then(() => {this.isPlaying = true;}).catch(error => {console.error('播放失败:', error);});});// 设置一个超时机制,防止长时间停留在加载状态const timeoutId = setTimeout(() => {console.warn('视频加载超时');// 尝试重新加载视频this.player.src({ src: this.videoSrc, type: 'application/x-mpegURL' });this.player.load();}, 10000); // 10秒超时// 当视频加载完成时清除超时this.player.on('loadeddata', () => clearTimeout(timeoutId));} catch (error) {console.error('更新视频源并准备播放失败:', error);}
    }

    4. 用户交互限制

  • 问题:某些浏览器要求视频播放必须在用户交互后触发,如果未正确处理用户交互,可能导致视频无法播放。

  • 影响:视频无法自动播放,用户需要手动点击播放按钮。

  • 解决方案:在用户交互后触发视频播放。

handleTouchEnd(event) {this.touchEndY = event.changedTouches[0].clientY;this.handleSwipe();this.isUserInteracted = true; // 标记用户交互if (this.player && this.isUserInteracted) {this.player.play().catch(error => {console.error('播放失败:', error);});}
}

5. 播放器初始化问题

  • 问题:播放器初始化逻辑中,this.$video 未定义,可能导致播放器无法正确初始化。

  • 影响:播放器无法正常工作。

  • 解决方案:使用 videojs 直接初始化播放器。

    initplayer() {let video = document.createElement('video');video.id = 'video';video.preload = "auto";video.setAttribute('playsinline', true);video.setAttribute('webkit-playsinline', true);video.setAttribute('x5-video-player-type', 'h5');let source = document.createElement('source');source.src = this.videoSrc;video.appendChild(source);this.$refs.videos.appendChild(video);this.player = videojs(video, {autoplay: false,controls: !this.isAdVideo,sources: [{ src: this.videoSrc, type: 'application/x-mpegURL' }]});this.player.on('error', (error) => {console.error('视频加载错误:', error);});
    }

    6. 播放器销毁问题

  • 问题:在 beforeDestroy 钩子中,播放器销毁逻辑可能无法正确执行。

  • 影响:播放器实例可能未正确销毁,导致内存泄漏。

  • 解决方案:确保播放器实例被正确销毁。

    beforeDestroy() {if (this.player) {console.log('播放器正在销毁');this.player.dispose();this.player = null;} else {console.log('未找到播放器实例,可能未初始化');}
    }

    7. 日志输出不足

  • 问题:日志输出较少,难以定位问题。

  • 影响:调试困难。

  • 解决方案:在关键步骤添加日志输出。

    console.log('即将更新视频源为:', this.videoSrc);
    console.log('currentIndex:', this.currentIndex);
    console.log('videos长度:', this.videos.length);

    8. 广告视频逻辑问题

  • 问题:广告视频的逻辑中,nextVideo.ad.urll 拼写错误。

  • 影响:广告 URL 无法正确更新。

  • 解决方案:修正拼写错误。

    if (this.isAdVideo) {this.adUrl = nextVideo.ad.url; // 修正拼写错误
    } else {this.adUrl = '';
    }

  • 五、完整代码

  • <template><view @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd"><!-- 视频容器 --><div id="app"><div class="video-js" ref="videos"></div></div></view>
    </template><script>
    import { baseUrl } from '@/common/api.js';
    import videojs from 'video.js';
    import 'video.js/dist/video-js.css'; // 引入默认样式export default {name: 'VideoPlayer',data() {return {videoSrc: '',isAdVideo: false,adUrl: '',currentIndex: 0,videos: [],touchStartY: 0,touchEndY: 0,player: null, // video.js 的播放器实例uniqueKey: Date.now(), // 用于强制刷新组件isPlaying: false, // 跟踪播放状态isUserInteracted: false, // 跟踪用户交互状态};},onLoad(options) {this.initFromOptions(options);},activated() {// 当组件被激活时(从缓存中恢复),重新初始化播放器this.$nextTick(() => this.initplayer());},deactivated() {// 当组件被停用时(进入缓存),销毁播放器this.destroyPlayer();},mounted() {// 确保在挂载时初始化播放器this.$nextTick(() => this.initplayer());},methods: {async initFromOptions(options) {const videoFile = options.videoFile;const isAd = options.isAd === 'true';const adUrl = options.adUrl ? decodeURIComponent(options.adUrl) : '';const videos = options.videos ? JSON.parse(decodeURIComponent(options.videos)) : [];this.isAdVideo = isAd;this.adUrl = adUrl;this.videos = videos;if (isAd) {this.videoSrc = `${baseUrl}${videoFile}`.replace(/\\/g, '/');} else {const video = videos.find(v => v.m3u8_url === videoFile);if (video) {this.videoSrc = `${baseUrl}${video.m3u8_url}`.replace(/\\/g, '/');} else {console.error('未找到对应的视频文件路径');return;}}this.currentIndex = this.videos.findIndex(v => {if (this.isAdVideo) {return v.ad && v.ad.m3u8_url === videoFile;}return v.m3u8_url === videoFile;});console.log('Initial video file:', this.videoSrc);await this.initplayer(); // 确保播放器初始化完成},async initplayer() {// 如果播放器已经存在,则更新源而不是重新创建if (this.player) {await this.updateVideoSource();return;}let videoElement = document.createElement('video');videoElement.id = 'video';videoElement.preload = "auto";videoElement.setAttribute('playsinline', true);videoElement.setAttribute('webkit-playsinline', true);videoElement.setAttribute('x5-video-player-type', 'h5');let source = document.createElement('source');source.src = this.videoSrc;videoElement.appendChild(source);this.$refs.videos.appendChild(videoElement);// 使用 Vue 的 nextTick 方法确保 DOM 更新完成后才初始化 Video.js 播放器this.$nextTick(() => {this.player = videojs(videoElement,{autoplay: false,controls: !this.isAdVideo,sources: [{ src: this.videoSrc, type: 'application/x-mpegURL' }]},async function onPlayerReady() {console.log("播放器已准备好");try {if (this.isUserInteracted) {await this.play(); // 使用 async/await 确保 play() 完成}} catch (error) {console.error('播放失败:', error);}}.bind(this));// 监听错误事件this.player.on('error', (error) => {console.error('视频加载错误:', error);console.error('错误详情:', this.player.error()); // 获取详细的错误信息});});},destroyPlayer() {if (this.player) {console.log('播放器正在销毁');this.player.dispose();this.player = null; // 清除 player 实例引用} else {console.log('未找到播放器实例,可能未初始化');}},async updateVideoSource() {if (!this.player) return;console.log('正在更新视频源:', this.videoSrc);try {this.player.pause(); // 暂停当前播放this.player.src({ src: this.videoSrc, type: 'application/x-mpegURL' });this.player.load();// 监听 loadeddata 事件,确保视频数据加载完成后再尝试播放this.player.one('loadeddata', () => {console.log('视频数据加载完成');this.isPlaying = false;this.player.play().then(() => {this.isPlaying = true;}).catch(error => {console.error('播放失败:', error);// 可以在这里添加重试逻辑或提示用户});});// 设置一个超时机制,防止长时间停留在加载状态const timeoutId = setTimeout(() => {console.warn('视频加载超时');// 尝试重新加载视频this.player.src({ src: this.videoSrc, type: 'application/x-mpegURL' });this.player.load();}, 10000); // 10秒超时// 当视频加载完成时清除超时this.player.on('loadeddata', () => clearTimeout(timeoutId));} catch (error) {console.error('更新视频源并准备播放失败:', error);// 可以在这里添加重试逻辑或提示用户}},handleTouchStart(event) {this.touchStartY = event.touches[0].clientY;},handleTouchMove(event) {// 这里可以添加优化逻辑,但目前保持原样},handleTouchEnd(event) {this.touchEndY = event.changedTouches[0].clientY;this.handleSwipe();this.isUserInteracted = true; // 标记用户交互if (this.player && this.isUserInteracted) {this.player.play().catch(error => {console.error('播放失败:', error);});}},handleSwipe() {const distance = this.touchEndY - this.touchStartY;if (Math.abs(distance) < 30) return;if (distance > 0) {this.handleSwipeDown();} else {this.handleSwipeUp();}},handleSwipeUp() {if (this.currentIndex < this.videos.length - 1) {this.currentIndex++;this.updateVideo();console.log('Swipe Up: Next video file:', this.videoSrc);console.log('是否广告', this.isAdVideo);} else {console.log("已经是最后一个视频了");}},handleSwipeDown() {if (this.currentIndex > 0) {this.currentIndex--;this.updateVideo();console.log('Swipe Down: Previous video file:', this.videoSrc);} else {console.log("已经是第一个视频了");}},updateVideo() {const nextVideo = this.videos[this.currentIndex];this.isAdVideo = !!nextVideo.ad;if (this.isAdVideo) {this.videoSrc = `${baseUrl}${nextVideo.ad.m3u8_url}`.replace(/\\/g, '/');} else {this.videoSrc = `${baseUrl}${nextVideo.m3u8_url}`.replace(/\\/g, '/');}this.adUrl = this.isAdVideo ? nextVideo.ad.url : '';console.log('即将更新视频源为:', this.videoSrc); // 添加日志输出console.log('currentIndex:', this.currentIndex); // 添加日志输出console.log('videos长度:', this.videos.length); // 添加日志输出this.destroyPlayer(); // 销毁旧的播放器实例this.$nextTick(() => {this.initplayer(); // 重新初始化播放器});},handleVideoClick() {if (this.isAdVideo && this.adUrl) {if (process.env.VUE_APP_PLATFORM === 'h5') {window.open(this.adUrl, '_blank');} else {uni.navigateTo({url: `/pages/webview/webview?url=${encodeURIComponent(this.adUrl)}`});}}}},watch: {// 监听路由变化并强制刷新组件$route(to, from) {this.uniqueKey = Date.now(); // 改变 key 来强制刷新组件this.$nextTick(() => this.initplayer()); // 确保播放器在路由变化后重新初始化}}
    };
    </script><style scoped>
    /* 添加样式 */
    #app {width: 100%;height: 100%;
    }
    .video-js {width: 100%;height: 100%;
    }
    </style>


  • 总结

    通过修复视频路径格式、确保播放器正确销毁和重新初始化、处理视频加载超时、确保用户交互后播放、修正播放器初始化逻辑以及修正广告视频逻辑,可以有效解决视频切换时一直加载的问题。如果问题仍然存在,建议进一步检查视频源的有效性和网络状态,并使用浏览器的开发者工具查看网络请求和错误日志。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/67274.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P3数据结构、数据类型、数字编码、字符编码:保姆级图文详解

文章目录 前言1、数据结构分类1.1、逻辑结构&#xff1a;线性与非线性1.2、物理结构&#xff1a;连续与分散1.3、数据结构的实现方式1.4、数据结构的选择依据 2、基本数据类型2.1、定义与分类2.2、存储形式 3、数字编码3.1、原码、反码与补码3.2、浮点数编码3.3、整数与浮点数区…

解密AIGC三大核心算法:GAN、Transformer、Diffusion Models原理与应用

在当今数字化时代&#xff0c;人工智能生成内容&#xff08;AIGC&#xff09;技术正以前所未有的速度改变着我们的生活和工作方式。从创意无限的文本生成&#xff0c;到栩栩如生的图像创作&#xff0c;再到动听的音乐旋律&#xff0c;AIGC的魔力无处不在。而这一切的背后&#…

Web前端------HTML表格

一.表格标签介绍 表格&#xff0c;类似操作的软件excel一样&#xff0c;通过规范的行列方式展示数据的一种视图&#xff01; 网页中&#xff08;初级开发&#xff09;&#xff0c;对于这种规范的数据&#xff0c;使用表格标签最方便的&#xff1b; 实际开发&#xff08;高级开…

nginx 配置域名前缀访问 react 项目

说明一下&#xff1a;我是使用域名转发访问的&#xff0c;访问流程如下&#xff1a; 浏览器 》 服务器1 》 服务器2 由于服务器1已经为 https 的访问方式做了 ssl 证书等相关配置&#xff0c;然后转发到服务器2&#xff0c; 所以在服务器2中不需要再配置 ssl 证书相关的东西了&…

imbinarize函数用法详解与示例

一、函数概述 众所周知&#xff0c;im2bw函数可以将灰度图像转换为二值图像。但MATLAB中还有一个imbinarize函数可以将灰度图像转换为二值图像。imbinarize函数是MATLAB图像处理工具箱中用于将灰度图像或体数据二值化的工具。它可以通过全局或自适应阈值方法将灰度图像转换为二…

数仓建模(三)建模三步走:需求分析、模型设计与数据加载

本文包含&#xff1a; 数据仓库的背景与重要性数据仓库建模的核心目标本文结构概览&#xff1a;需求分析、模型设计与数据加载 目录 第一部分&#xff1a;需求分析 1.1 需求分析的定义与目标 1.2 需求分析的步骤 1.2.1 业务需求收集 1.2.2 技术需求分析 1.2.3 成果输出…

【C++指南】类和对象(八):匿名对象

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 引言 在C编程中&#xff0c;匿名对象是一种特殊的对象&#xff0c;它在创建时没有被命名。 这种对象通常用…

编译pytorch——cuda-toolkit-nvcc

链接 https://blog.csdn.net/wjinjie/article/details/108997692https://docs.nvidia.com/cuda/cuda-installation-guide-linux/#switching-between-driver-module-flavorshttps://forums.developer.nvidia.com/t/can-not-load-nvidia-drivers-on-ubuntu-22-10/239750https://…

智汇云舟参编《城市轨道交通安全防范系统技术要求》国标正式发布

近日&#xff0c;根据国家标准化管理委员会官网&#xff0c;全国标准信息公共服务平台发布的公告&#xff0c;国家标准《城市轨道交通安全防范系统技术要求》&#xff08;GB/T 26718-2024&#xff09;已由全国城市轨道交通标准化技术委员会上报国家标准化管理委员会&#xff0c…

Unity解决滑动条的value值的滑动条消失问题

在这里我们看到原本的value的滑动条消失了 解决办法 把编辑器的边框往外面拉一下就可以了&#xff08;之前遇到这个问题还重启了几次unity没想到居然是这个问题&#xff09;

HarmonyOS应用开发者初级认证最新版– 2025/1/13号题库新版

1.欢迎各位读者&#xff0c;本文档来自鸿蒙开发学员亲测&#xff0c;最新版。&#xff08;考试时直接Ctrlf进行搜索&#xff0c;一定要认真比对答案&#xff0c;有的答案相似度很高&#xff09;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 欢迎…

kubernetes v1.29.XX版本HPA、KPA、VPA并压力测试

序言&#xff1a; 在大型电商、购物、直播活动期间&#xff0c;对于火爆流量的激增&#xff0c;如何保障业务稳定并且做到资源不浪费&#xff0c;自动回收。 场景&#xff1a;kubernetes 原生容器化承载业务流量&#xff08;非云环境&#xff09; 方案&#xff1a;kubernetes自…

HarmonyOS NEXT应用开发边学边玩系列:从零实现一影视APP (五、电影详情页的设计实现)

在上一篇文章中&#xff0c;完成了电影列表页的开发。接下来&#xff0c;将进入电影详情页的设计实现阶段。这个页面将展示电影的详细信息&#xff0c;包括电影海报、评分、简介以及相关影人等。将使用 HarmonyOS 提供的常用组件&#xff0c;并结合第三方库 nutpi/axios 来实现…

Vulnhub DC-8靶机攻击实战(一)

导语   Vulnhub DC-8靶机教程来了,好久没有更新打靶的教程了,这次我们在来更新一期关于Vulnhub DC-8的打靶训练,如下所示。 安装并且启动靶机 安装并且启动靶机,如下所示。 开始信息采集 进入到Kali中,通过如下的命令来查找到靶机的IP地址。 arp-scan -l根据上面的结…

神经网络基础-正则化方法

文章目录 1. 什么是正则化2. 正则化方法2.1 Dropout正则化2.2 批量归一化(BN层) 学习目标&#xff1a; 知道正则化的作用掌握随机失活 DropOut 策略知道 BN 层的作用 1. 什么是正则化 在设计机器学习算法时希望在新样本上的泛化能力强。许多机器学习算法都采用相关的策略来减小…

【Linux】12.Linux进程概念(1)

文章目录 1. 冯诺依曼体系结构2. 操作系统(Operator System)概念设计OS的目的胆小的操作系统定位如何理解 "管理"总结 3. 进程基本概念task_struct-PCB的一种task_ struct内容分类组织进程查看进程通过系统调用获取进程标示符通过系统调用创建进程-fork初识 1. 冯诺依…

【Linux网络编程】序列化与反序列化

目录 一&#xff0c;序列化和反序列化的说明 二&#xff0c;Jsoncpp库的介绍 三&#xff0c;Jsoncpp库的使用 3-1&#xff0c;Json::Value类 3-2&#xff0c;Json::StreamWriter类 3-3&#xff0c;Json::CharReader类 一&#xff0c;序列化和反序列化的说明 序列化与反…

Oracle报错ORA-01078、LRM-00109

虚拟机异常关机后&#xff0c;rac数据库备机无法启动数据库&#xff0c;报错如下 解决方法&#xff1a; 找到如下路径文件 执行&#xff1a; cp init.ora.016202516818 /u01/app/oracle/product/19.3.0/db/dbs/ mv init.ora.016202516818 initplm2.ora 再次进入命令行sqlpl…

STM32-keil安装时遇到的一些问题以及解决方案

前言&#xff1a; 本人项目需要使用到STM32,故需配置keil 5&#xff0c;在配置时遇到了以下问题&#xff0c;并找到相应的解决方案&#xff0c;希望能够为遇到相同问题的道友提供一些解决思路 1、提示缺少&#xff08;missing&#xff09;version 5编译器 step1&#xff1a;找…

【Hive】海量数据存储利器之Hive库原理初探

文章目录 一、背景二、数据仓库2.1 数据仓库概念2.2 数据仓库分层架构2.2.1 数仓分层思想和标准2.2.2 阿里巴巴数仓3层架构2.2.3 ETL和ELT2.2.4 为什么要分层 2.3 数据仓库特征2.3.1 面向主题性2.3.2 集成性2.3.3 非易失性2.3.4 时变性 三、hive库3.1 hive概述3.2 hive架构3.2.…