UniApp实现漂亮的音乐歌词滚动播放效果

2024-09-08 06:28

本文主要是介绍UniApp实现漂亮的音乐歌词滚动播放效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在现代的音乐播放应用中,歌词的展示和滚动播放已经成为了一个非常常见的功能。今天,我们将通过UniApp来实现一个漂亮的歌词滚动播放功能。我们将使用UniApp提供的组件和API来完成这个任务。

页面结构

在页面的模板部分,我们需要创建一个音频播放器和歌词展示区域。使用<scroll-view>组件来实现歌词的滚动效果。

<template><view class="audio-container"><!-- 音频播放器 --><view class="audio-player"><audio :src="audioSrc" @timeupdate="updateTime" @ended="audioEnded"></audio><view class="controls"><button @click="playAudio">播放</button><button @click="pauseAudio">暂停</button></view><view class="time">{{ currentTime }} / {{ duration }}</view></view><!-- 歌词展示区域 --><scroll-view class="lyrics" scroll-y :scroll-top="scrollTop"><view v-for="(line, index) in lyrics" :key="index" :class="{ active: currentLineIndex === index }">{{ line.text }}</view></scroll-view></view>
</template>

脚本逻辑

在脚本部分,我们需要处理音频的播放、暂停、时间更新等事件,并根据当前播放时间更新歌词的显示和滚动位置。

<script>
export default {data() {return {audioSrc: 'https://example.com/audio.mp3', // 音频文件地址lyrics: [{ time: 0, text: '第一行歌词' },{ time: 5000, text: '第二行歌词' },{ time: 10000, text: '第三行歌词' },// 更多歌词行...],currentTime: '00:00', // 当前播放时间duration: '00:00', // 音频总时长currentLineIndex: 0, // 当前高亮的歌词行索引scrollTop: 0, // 歌词滚动位置};},methods: {playAudio() {const audio = document.querySelector('audio');audio.play();},pauseAudio() {const audio = document.querySelector('audio');audio.pause();},updateTime(event) {const audio = event.target;this.currentTime = this.formatTime(audio.currentTime);this.duration = this.formatTime(audio.duration);this.updateLyrics(audio.currentTime * 1000); // 转换为毫秒},audioEnded() {this.currentTime = '00:00';this.currentLineIndex = 0;this.scrollTop = 0;},updateLyrics(currentTime) {for (let i = 0; i < this.lyrics.length; i++) {if (currentTime >= this.lyrics[i].time) {this.currentLineIndex = i;} else {break;}}this.scrollLyrics();},scrollLyrics() {const lineHeight = 30; // 每行歌词的高度this.scrollTop = this.currentLineIndex * lineHeight;},formatTime(time) {const minutes = Math.floor(time / 60);const seconds = Math.floor(time % 60);return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;},},
};
</script>

样式设计

在样式部分,我们可以设计音频播放器和歌词展示区域的样式,使其看起来更加美观。

<style scoped>
.audio-container {padding: 20px;
}.audio-player {margin-bottom: 20px;
}.controls {margin-bottom: 10px;
}.time {font-size: 14px;color: #666;
}.lyrics {height: 300px;overflow-y: auto;border: 1px solid #ccc;padding: 10px;font-size: 16px;line-height: 1.5;text-align: center;
}.lyrics view {transition: color 0.3s ease;
}.lyrics .active {color: #ff6600;font-weight: bold;
}
</style>

运行效果

通过以上步骤,你可以在UniApp中实现一个漂亮的音乐歌词滚动播放效果。运行项目后,你应该能够看到一个带有播放、暂停按钮的音频播放器,以及随着音乐播放自动滚动的歌词。

app体验地址

项目开源地址:imovie: 爱电影小程序uni-app

歌词解析

 网络上拿到的歌词,可能是类似如下格式:

{"songStatus":1,"lyricVersion":3,"lyric":"[by:有个陷阱他们早就已经沦陷]\n\n[00:09.23]\n[00:20.20]花的心藏在蕊中\n[00:23.80]空把花期都错过\n[00:27.26]\n[00:29.52]你的心忘了季节\n[00:33.12]从不轻易让人懂\n[00:37.24]\n[00:38.81]为何不牵我的手\n[00:42.49]共听日月唱首歌\n[00:46.09]\n[00:47.46]黑夜又白昼\n[00:49.72]黑夜又白昼\n[00:51.73]人生为欢有几何\n[00:55.54]\n[00:57.00]春去春会来\n[01:01.72]花谢花会再开\n[01:06.08]只要你愿意\n[01:08.39]只要你愿意\n[01:10.41]让梦划向你心海\n[01:15.65]春去春会来\n[01:20.32]花谢花会再开\n[01:24.73]只要你愿意\n[01:27.06]只要你愿意\n[01:29.02]让梦划向你心海\n[01:33.43]\n[02:12.13]花瓣泪飘落风中\n[02:15.73]虽有悲意也从容\n[02:19.33]\n[02:21.41]你的泪晶莹剔透\n[02:25.04]心中一定还有梦\n[02:29.30]\n[02:30.73]为何不牵我的手\n[02:34.38]同看海天成一色\n[02:39.36]潮起又潮落\n[02:41.68]潮起又潮落\n[02:43.68]送走人间许多愁\n[02:48.28]\n[02:48.99]春去春会来\n[02:53.61]花谢花会再开\n[02:57.98]只要你愿意\n[03:00.35]只要你愿意\n[03:02.32]让梦划向你心海\n[03:07.58]春去春会来\n[03:12.32]花谢花会再开\n[03:16.58]只要你愿意\n[03:18.95]只要你愿意\n[03:21.01]让梦划向你心海\n[03:26.23]只要你愿意\n[03:28.29]只要你愿意\n[03:30.26]让梦划向你心海\n[03:35.06]\n","code":200}

需要对其解析,解析为类似以下的格式:

lyrics: [{ time: 0, text: '第一行歌词' },{ time: 5000, text: '第二行歌词' },{ time: 10000, text: '第三行歌词' },// 更多歌词行...],

解析方法:

/*** 歌词解析* @param {lrcContent} string - 歌词内容* @returns {lyrics} 对象数组*/
function parseLyric(lrcContent) {const lines = lrcContent.split('\n');const lyrics = [];lines.forEach(line => {const match = line.match(/\[(\d{2}):(\d{2})\.(\d{2,3})\]/);if (match) {const minutes = parseInt(match[1]);const seconds = parseInt(match[2]);const milliseconds = parseInt(match[3]);const time = minutes * 60 * 1000 + seconds * 1000 + milliseconds;// 提取歌词文本const text = line.replace(/\[\d{2}:\d{2}\.\d{2,3}\]/g, '').trim();lyrics.push({ time, text });}});return lyrics;
}

完成audio组件源码

<template><view class="audio_container"><view class="audio-title"style="width: 100%; text-align: left; font-size: 36rpx;font-weight: bold;padding: 0rpx 0rpx; position: relative;"><uni-notice-bar single :scrollable="titleScroll" :size="titleFontSize":background-color="titleBackgroundColor" :color="titleColor" :speed="titleScrollSpeed" :text="title"class="uni-noticebar" style="padding: 0px; margin-bottom: 0px;"></uni-notice-bar><uni-fav v-show="isCollectBtn" :checked="isFavorited" class="favBtn"  bgColor="#dddddd" bgColorChecked="#ffaa00" @click="handleCollec"style="color:#848484; position: absolute;top: 0rpx;right: 0px;"></uni-fav></view><view class="audio-subTitle":style="'font-size: '+subTitleFontSize+';font-weight: bold;padding: 0rpx 0rpx 4rpx 0rpx;position: relative;'"><uni-notice-bar single :scrollable="titleScroll" :size="titleFontSize":background-color="titleBackgroundColor" :color="subTitleColor" :speed="titleScrollSpeed":text="localSubTitle" class="uni-noticebar"></uni-notice-bar><uni-icons v-show="isShareBtn" @click="handleShare" type="redo" size="20"style="color:#848484;position: absolute;top: 0rpx;right: 0px;"></uni-icons></view><view><slider :backgroundColor='backgroundColor' :activeColor='activeColor' @change="handleSliderChange":value="sliderIndex" :max="maxSliderIndex" block-color="#343434" block-size="16" /></view><view style="padding: 0rpx 15rpx 0rpx 15rpx ; display: block; "><view style="float: left; font-size: 20rpx;color:#848484;">{{currentTimeText}}</view><view style="float: right;font-size: 20rpx;color:#848484;">{{totalTimeText}}</view></view><view style="margin-top: 70rpx;"><uni-grid :column="5" :showBorder="false" :square="false"><uni-grid-item><view class="uni-grid-icon"><image @tap="handleFastRewind" src="../../static/images/playlist.svg"style="width: 48rpx;height: 48rpx;top:6rpx;"></image></view></uni-grid-item><uni-grid-item><view class="uni-grid-icon"><image @tap="handleFastRewind" src="../../static/images/get-back.svg"style="width: 48rpx;height: 48rpx;top:6rpx;"></image></view></uni-grid-item><uni-grid-item><view class="uni-grid-icon"><image @tap="handleChangeAudioState" v-show="!isPlaying" src="../../static/images/play.svg"style="width: 48rpx;height: 48rpx;top:6rpx;"></image><image @tap="handleChangeAudioState" v-show="isPlaying" src="../../static/images/pause.svg"style="width: 48rpx;height: 48rpx;top:6rpx;"></image></view></uni-grid-item><uni-grid-item><view class="uni-grid-icon"><image @tap="handleFastForward" src="../../static/images/fast-forward.svg"style="width: 48rpx;height: 48rpx;top:6rpx;"></image></view></uni-grid-item><uni-grid-item><view class="uni-grid-icon"><image @tap="handleLoopPlay" src="../../static/images/Loop.svg"style="width: 48rpx;height: 48rpx; top:6rpx; "></image></view></uni-grid-item></uni-grid></view><view v-show="isShowLrc"><scroll-view class="lyrics" scroll-y :scroll-top="scrollTop" :current="currentLineIndex" ref="lyricsContainer" ><block v-for="(line, index) in lyrics" :key="index"><view :class="{ 'active': currentLineIndex === index }">{{ line.text }}</view></block></scroll-view></view></view>
</template>
<script>export default {name: 'my-audio',//audioPlay开始播放//audioPause停止播放//audioEnd音频自然播放结束事件//audioCanplay音频进入可以播放状态,但不保证后面可以流畅播放//change播放状态改变 返回值false停止播放 true开始播放//audioError 播放器错误//audioCollec 音频收藏emits: ['audioPlay', 'audioPause', 'audioEnd', 'audioCanplay', 'change', 'audioError','audioCollec'],props: {//标题文字title: {type: String,default: '空'},//标题默认字体大小titleFontSize: {type: Number,default: 35},//标题文字颜色titleColor: {type: String,default: '#303030'},//标题背景色titleBackgroundColor: {type: String,default: 'white'},//标题是否滚动titleScroll: {type: Boolean,default: false},//标题滚动速度titleScrollSpeed: {type: Number,default: 100},subTitle: {type: String,default: '空'},subTitleColor: {type: String,default: '#6C7996'},subTitleFontSize: {type: String,default: "30rpx"},//是否自动播放autoplay: {type: Boolean,default: false},//滑块左侧已选择部分的线条颜色activeColor: {type: String,default: '#7C7C7C'},//滑块右侧背景条的颜色backgroundColor: {type: String,default: '#E5E5E5'},//音频地址src: {type: [String, Array],default: ''},//是否倒计时isCountDown: {type: Boolean,default: false},//音乐封面audioCover: {type: String,default: ''},//是否显示收藏按钮isCollectBtn: {type: Boolean,default: false},//状态是否是已收藏isFavorited: {type: Boolean,default: false},//是否显示分享按钮isShareBtn: {type: Boolean,default: false},//是否显示歌词isShowLrc: {type: Boolean,default: false},//歌词信息lyrics: {type: [Array],default: []},},data() {return {totalTimeText: '00:00', //视频总长度文字currentTimeText: '00:00:00', //视频已播放长度文字isPlaying: false, //播放状态sliderIndex: 0, //滑块当前值maxSliderIndex: 100, //滑块最大值IsReadyPlay: false, //是否已经准备好可以播放了isLoop: false, //是否循环播放speedValue: [0.5, 0.8, 1.0, 1.25, 1.5, 2.0],speedValueIndex: 2,playSpeed: '1.0', //播放倍速 可取值:0.5/0.8/1.0/1.25/1.5/2.0currentLineIndex: 0,localSubTitle:this.subTitle,shortLrc:'',scrollTop: 0, // 初始滚动位置stringObject: (data) => {return typeof(data)},innerAudioContext: uni.createInnerAudioContext()}},watch: {subTitle(newVal) {this.localSubTitle = newVal;}},async mounted() {this.innerAudioContext.src = typeof(this.src) == 'string' ? this.src : this.src[0];if (this.autoplay) {if (!this.src) return console.error('src cannot be empty,The target value is string or array')// #ifdef H5var ua = window.navigator.userAgent.toLowerCase();if (ua.match(/MicroMessenger/i) == 'micromessenger') {const jweixin = require('../../utils/jweixin');jweixin.config({});jweixin.ready(() => {WeixinJSBridge.invoke('getNetworkType', {}, (e) => {this.innerAudioContext.play();})})}// #endif// #ifndef H5this.innerAudioContext.autoplay = true;// #endif}//音频播放事件this.innerAudioContext.onPlay(() => {this.isPlaying = true;this.$emit('audioPlay')this.$emit('change', {state: true});setTimeout(() => {this.maxSliderIndex = parseFloat(this.innerAudioContext.duration).toFixed(2);}, 100)});//音频暂停事件this.innerAudioContext.onPause(() => {this.$emit('audioPause');this.$emit('change', {state: false});});//音频自然播放结束事件this.innerAudioContext.onEnded(() => {this.isPlaying = !this.isPlaying;this.$emit('audioEnd');if (this.isLoop) {this.changePlayProgress(0);this.innerAudioContext.play();}});//音频进入可以播放状态,但不保证后面可以流畅播放this.innerAudioContext.onCanplay((event) => {this.IsReadyPlay = true;this.$emit('audioCanplay');let duration = this.innerAudioContext.duration;//console.log('总时长', duration)//将当前音频长度秒转换为00:00:00格式this.totalTimeText = this.getFormateTime(duration);this.maxSliderIndex = parseFloat(duration).toFixed(2);//console.log(this.getFormateTime(duration))//console.log('总时长1', this.totalTimeText)//防止视频无法正确获取时长setTimeout(() => {duration = this.innerAudioContext.duration;//将当前音频长度秒转换为00:00:00格式this.totalTimeText = this.getFormateTime(duration);this.maxSliderIndex = parseFloat(duration).toFixed(2);//console.log('总时长2', this.totalTimeText)}, 300)});//音频播放错误事件this.innerAudioContext.onTimeUpdate((res) => {this.sliderIndex = parseFloat(this.innerAudioContext.currentTime).toFixed(2);this.currentTimeText = this.getFormateTime(this.innerAudioContext.currentTime);//更新歌词const currentTime = this.innerAudioContext.currentTime * 1000; // 转换为毫秒this.updateLyrics(currentTime);});//音频播放错误事件this.innerAudioContext.onError((res) => {console.log(res.errMsg);console.log(res.errCode);this.$emit('change', {state: false});this.audioPause();this.$emit('audioError', res);});},methods: {//销毁innerAudioContext()实例audioDestroy() {console.log("audioDestroy")if (this.innerAudioContext) {if (this.isPlaying && !this.innerAudioContext.paused) {this.audioPause();}this.innerAudioContext.destroy();this.isPlaying = false;}},//点击变更播放状态handleChangeAudioState() {if(this.src ===''){uni.showToast({title: '无播放资源',icon: 'none',duration: 1000});return;}if (this.isPlaying && !this.innerAudioContext.paused) {this.audioPause();} else {this.audioPlay();}},//开始播放audioPlay() {this.$nextTick(() => {this.innerAudioContext.src = this.src;setTimeout(() => {this.innerAudioContext.play();this.isPlaying = true;}, 100); // 100毫秒});},//暂停播放audioPause() {this.innerAudioContext.pause();this.isPlaying = false;},//变更滑块位置handleSliderChange(e) {this.changePlayProgress(e.detail ? e.detail.value : e)},//更改播放倍速handleChageSpeed() {//获取播放倍速列表长度let speedCount = this.speedValue.length;//如果当前是最大倍速,从-1开始if (this.speedValueIndex == (speedCount - 1)) {this.speedValueIndex = -1;}//最新倍速序号this.speedValueIndex += 1;//获取最新倍速文字this.playSpeed = this.speedValue[this.speedValueIndex].toFixed(1);//暂停播放this.audioPause();//变更播放倍速this.innerAudioContext.playbackRate(this.speedValue[this.speedValueIndex]);//开始播放this.audioPlay();},//快退15秒handleFastRewind() {if (this.IsReadyPlay) {let value = parseInt(this.sliderIndex) - 15;this.changePlayProgress(value >= 0 ? value : 0);}},//快进15秒handleFastForward() {if (this.IsReadyPlay) {let value = parseInt(this.sliderIndex) + 15;this.changePlayProgress(value <= this.innerAudioContext.duration ? value : this.innerAudioContext.duration);}},//开启循环播放handleLoopPlay() {this.isLoop = !this.isLoop;if (this.isLoop) {uni.showToast({title: '已开启循环播放',duration: 1000});} else {uni.showToast({title: '取消循环播放',duration: 1000});}},//更改播放进度changePlayProgress(value) {this.innerAudioContext.seek(value);this.sliderIndex = value;this.currentTimeText = this.getFormateTime(value);},//秒转换为00:00:00getFormateTime(time) {let ms = time * 1000; // 1485000毫秒let date = new Date(ms);// 注意这里是使用的getUTCHours()方法,转换成UTC(协调世界时)时间的小时let hour = date.getUTCHours();// let hour = date.getHours(); 如果直接使用getHours()方法,则得到的时分秒格式会多出来8个小时(在国内开发基本都是使用的是东八区时间),getHours()方法会把当前的时区给加上。let minute = date.getMinutes();let second = date.getSeconds();let formatTime =`${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}`;return formatTime;},handleCollec() {this.$emit('audioCollec');},handleShare() {this.$emit('audioShare');},updateLyrics(currentTime) {for (let i = 0; i < this.lyrics.length; i++) {if (currentTime >= this.lyrics[i].time) {this.currentLineIndex = i;this.shortLrc = this.lyrics[i].text;this.localSubTitle = this.subTitle + ' : '+this.shortLrc} else {break;}}this.scrollLyrics();},scrollLyrics() {const lineHeight = 20; // 每行歌词的高度this.scrollTop = this.currentLineIndex * lineHeight;},},onLoad() {console.log("onLoad")},onUnload() {console.log("onUnload")this.audioDestroy()},onHide() {console.log("onHide")this.audioDestroy()},beforeDestroy() {console.log("beforeDestroy")this.audioDestroy()}}
</script><style lang="scss" scoped>.audio_container {box-shadow: 0 0 10rpx #c3c3c3;padding: 30rpx 20rpx 30rpx 20rpx;.audio-title {font-size: 28rpx;}.uni-noticebar {padding: 0px;padding-right: 50rpx;margin-bottom: 0px;display: inline-block;}.audio-subTitle {width: 100%;text-align: left;font-size: 40rpx;color: blue;}.speed-text {position: absolute;top: 0rpx;left: 30rpx;right: 0;color: #475266;font-size: 16rpx;font-weight: 600;}.uni-grid-icon {text-align: center;}.lyrics {margin-top: 20px;height: 660rpx; /* 设置歌词容器的高度 */// overflow: hidden; /* 隐藏溢出的歌词 */overflow-y: auto; /* 允许垂直滚动 */position: relative;font-size: 32rpx;line-height: 1.8;text-align: center;}.lyrics view {transition: color 1.2s ease; /* 添加平滑颜色变化效果 */}.lyrics .active {color: #00aa00;font-size: 45rpx;font-weight: bold;}}
</style>

总结

通过使用UniApp的组件和API,我们可以轻松实现音乐歌词的滚动播放效果。关键在于监听音频的播放时间,并根据时间更新歌词的显示和滚动位置。

这里面有个悬而未决的问题,就是这个滚动显示,有时候会滚动到最上方或最下方,导致在视野区域看不到。以下的处理,虽然简单, 但也粗暴。原因就出在这里:

scrollLyrics() {const lineHeight = 20; // 每行歌词的高度this.scrollTop = this.currentLineIndex * lineHeight;
},

如何让歌词能够根据进度居中显示?有知道的欢迎留言,感谢!

其他资源

vue实现歌词滚动_vue 实现一个歌词滚动效果-CSDN博客

这篇关于UniApp实现漂亮的音乐歌词滚动播放效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147374

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

防近视护眼台灯什么牌子好?五款防近视效果好的护眼台灯推荐

在家里,灯具是属于离不开的家具,每个大大小小的地方都需要的照亮,所以一盏好灯是必不可少的,每个发挥着作用。而护眼台灯就起了一个保护眼睛,预防近视的作用。可以保护我们在学习,阅读的时候提供一个合适的光线环境,保护我们的眼睛。防近视护眼台灯什么牌子好?那我们怎么选择一个优秀的护眼台灯也是很重要,才能起到最大的护眼效果。下面五款防近视效果好的护眼台灯推荐: 一:六个推荐防近视效果好的护眼台灯的