uniapp音乐播放整理

一、前置知识点

1.1 音频组件控制-uni.createInnerAudioContext()

创建并返回内部 audio 上下文 innerAudioContext 对象。

主要用于当前音乐播放;

1.1.1 innerAudioContext属性
属性类型说明只读平台差异说明
srcString音频的数据链接,用于直接播放。微信小程序不支持本地路径
startTimeNumber开始播放的位置(单位:s),默认 0
autoplayBoolean是否自动开始播放,默认 falseH5端部分浏览器不支持
loopBoolean是否循环播放,默认 false
obeyMuteSwitchBoolean是否遵循系统静音开关,当此参数为 false 时,即使用户打开了静音开关,也能继续发出声音,默认值 true微信小程序、百度小程序、抖音小程序、飞书小程序、京东小程序、快手小程序(仅在 iOS 上生效)
durationNumber当前音频的长度(单位:s),只有在当前有合法的 src 时返回,需要在onCanplay中获取
currentTimeNumber当前音频的播放位置(单位:s),只有在当前有合法的 src 时返回,时间不取整,保留小数点后 6 位
pausedBoolean当前是是否暂停或停止状态,true 表示暂停或停止,false 表示正在播放
bufferedNumber音频缓冲的时间点,仅保证当前播放时间点到此时间点内容已缓冲。
volumeNumber音量。范围 0~1。
sessionCategoryString设置音频播放模式,可取值:“ambient” - 不中止其他声音播放,不能后台播放,静音后无声音; “soloAmbient” - 中止其他声音播放,不能后台播放,静音后无声音; “playback” - 中止其他声音,可以后台播放,静音后有声音。 默认值为"playback"。App 3.3.7+
playbackRateNumber播放的倍率。可取值:0.5/0.8/1.0/1.25/1.5/2.0,默认值为1.0App 3.4.5+(Android 需要 6 及以上版本)、微信小程序 2.11.0、支付宝小程序、抖音小程序 2.33.0+、快手小程序、百度小程序 3.120.2+
1.1.2 innerAudioContext方法列表
方法参数说明
play播放(H5端部分浏览器需在用户交互时进行)
pause暂停
stop停止
seekposition跳转到指定位置,单位 s
destroy销毁当前实例
onCanplaycallback音频进入可以播放状态,但不保证后面可以流畅播放
onPlaycallback音频播放事件
onPausecallback音频暂停事件
onStopcallback音频停止事件
onEndedcallback音频自然播放结束事件
onTimeUpdatecallback音频播放进度更新事件
onErrorcallback音频播放错误事件
onWaitingcallback音频加载中事件,当音频因为数据不足,需要停下来加载时会触发
onSeekingcallback音频进行 seek 操作事件
onSeekedcallback音频完成 seek 操作事件
offCanplaycallback取消监听 onCanplay 事件
offPlaycallback取消监听 onPlay 事件
offPausecallback取消监听 onPause 事件
offStopcallback取消监听 onStop 事件
offEndedcallback取消监听 onEnded 事件
offTimeUpdatecallback取消监听 onTimeUpdate 事件
offErrorcallback取消监听 onError 事件
offWaitingcallback取消监听 onWaiting 事件
offSeekingcallback取消监听 onSeeking 事件
offSeekedcallback取消监听 onSeeked 事件
1.1.3 简单示例
// 创建innerAudioContext对象
const innerAudioContext = uni.createInnerAudioContext();
// 开始自动播放
innerAudioContext.autoplay = true;
// 设置音频地址
innerAudioContext.src = 'url.mp3';
// 开始播放的回调函数
innerAudioContext.onPlay(() => {
  console.log('开始播放');
});
// 播放报错的事件监听
innerAudioContext.onError((res) => {
  console.log(res.errMsg);
  console.log(res.errCode);
});

1.2 背景音频控制-uni.getBackgroundAudioManager()

获取全局唯一的背景音频管理器 backgroundAudioManager

主要是实现后台播放功能,退出app或者小程序后还能继续播放,同时状态栏有控制播放状态控件;

1.2.1 backgroundAudioManager属性列表
属性类型说明只读
durationNumber当前音频的长度(单位:s),只有在当前有合法的 src 时返回
currentTimeNumber当前音频的播放位置(单位:s),只有在当前有合法的 src 时返回
pausedBoolean当前是是否暂停或停止状态,true 表示暂停或停止,false 表示正在播放
srcString音频的数据源,默认为空字符串,**当设置了新的 src 时,会自动开始播放,**目前支持的格式有 m4a, aac, mp3, wav
startTimeNumber音频开始播放的位置(单位:s)
bufferedNumber音频缓冲的时间点,仅保证当前播放时间点到此时间点内容已缓冲。
titleString音频标题,用于做原生音频播放器音频标题。原生音频播放器中的分享功能,分享出去的卡片标题,也将使用该值。
epnameString专辑名,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
singerString歌手名,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
coverImgUrlString封面图url,用于做原生音频播放器背景图。原生音频播放器中的分享功能,分享出去的卡片配图及背景也将使用该图。
webUrlString页面链接,原生音频播放器中的分享功能,分享出去的卡片简介,也将使用该值。
protocolString音频协议。默认值为 ‘http’,设置 ‘hls’ 可以支持播放 HLS 协议的直播音频,App平台暂不支持
playbackRateNumber播放的倍率。可取值:0.5/0.8/1.0/1.25/1.5/2.0,默认值为1.0。(App 3.4.5+、微信基础库 2.11.0+、支付宝小程序、抖音小程序 2.33.0+、快手小程序、百度小程序 3.120.2+)
1.2.2 backgroundAudioManager方法列表
方法参数说明
play播放
pause暂停
stop停止
seekposition跳转到指定位置,单位 s
onCanplaycallback背景音频进入可以播放状态,但不保证后面可以流畅播放
onPlaycallback背景音频播放事件
onPausecallback背景音频暂停事件
onStopcallback背景音频停止事件
onEndedcallback背景音频自然播放结束事件
onTimeUpdatecallback背景音频播放进度更新事件
onPrevcallback用户在系统音乐播放面板点击上一曲事件(iOS only)
onNextcallback用户在系统音乐播放面板点击下一曲事件(iOS only)
onErrorcallback背景音频播放错误事件
onWaitingcallback音频加载中事件,当音频因为数据不足,需要停下来加载时会触发
1.2.3 简单示例
// 创建bgAudioManager对象
const bgAudioManager = uni.getBackgroundAudioManager();
bgAudioManager.title = '音乐标题';
bgAudioManager.singer = '作者';
bgAudioManager.coverImgUrl = '封面图片';
bgAudioManager.src = 'url.mp3';
// 开始播放的回调函数
bgAudioManager.onPlay(() => {
  console.log('开始播放');
});
// 播放报错的事件监听
bgAudioManager.onError((res) => {
  console.log(res.errMsg);
  console.log(res.errCode);
});
1.2.4 注意点

注意 因为背景音频播放耗费手机电量,所以平台都有管控,需在manifest中填写申请。

  • ios App平台,背景播放需在manifest.json -> app-plus -> distribute -> ios 节点添加 "UIBackgroundModes":["audio"] 才能保证音乐可以后台播放(打包成ipa生效)
  • 小程序平台,需在manifest.json 对应的小程序节点下,填写"requiredBackgroundModes": [“audio”]。发布小程序时平台会审核

二、音乐功能点

2.1 实现效果

  1. 控制播放暂停;
  2. 实现上一首,下一首;
  3. 展示当前音乐当前进度时间,结束时间;展示当前音乐当前进度时间,结束时间;
  4. 可以通过进度条去控制音乐跳转到对应时间点;
  5. 实现倍速播放;
  6. 后台播放;

2.2 获取音乐信息

  1. 当前音乐播放状态;
  2. 音乐列表数据,便于实现上一首下一首;
  3. 当前音乐播放时长,与结束时长,播放速度;
  4. 音乐的地址、封面图片、名称等基础信息;
  5. 歌词展示,到达当前歌词时歌词高亮;

三、实现步骤

3.1 技术选型

通过前置知识点我们了解到了uni.createInnerAudioContext()和uni.getBackgroundAudioManager()的实例属性方法等。

可以根据需求去选择性调用实例,前者可以在小程序中调用来播放音乐;而如果想要退出小程序或者app后依然可以让音乐继续播放,这个时候就可以使用后者来生成悬浮框,以及状态栏中显示;

结论:

  1. 小程序或app中使用uni.createInnerAudioContext();
  2. 退出小程序或app时使用uni.getBackgroundAudioManager();

3.2 实现思路

根据前面整理的音乐所需功能点,我们需要使用store存储一些全局音乐状态信息;便于切换到其他界面的时候可以同步得到最新的音乐信息。

  1. 首先在程序初始化时,实例化一个audio对象挂载到vue原型上;
  2. 用于实时获取当前播放信息;
  3. 初始化时就可以把需要的监听事件挂载,配合实际业务场景;

3.3 简易代码示例

3.3.1 实例化挂载audio对象

入口文件实例化-main.js

// 新建音乐对象挂载到原型上
const innerAudioContext = uni.createInnerAudioContext();
// 音乐播放报错监听
innerAudioContext.onError((res) => {
  console.log("音乐播放报错监听", res);
});
// 音乐加载中监听
innerAudioContext.onWaiting((res) => {
  console.log("音乐加载中监听", res);
});
Vue.prototype.$AudioContext = innerAudioContext;
3.3.2 定义一个简单的音乐列表
{
// 滚动条信息
playInfo: {
        progressWidth: 2, 	// 滚动条
        currentTime: 0,			// 当前音乐时间s
        currentValue: '00:00', // 转换成时间展示
        duration: 0,				// 当前音乐总时间s
        durationValue: '00:00',	// 总时间转换展示 
    },
// 简易歌曲列表
audioList: [ 
	{
		title: '未完成之前',
		src: 'https://music.163.com/song/media/outer/url?id=1453946527.mp3',
		id: 1453946527,
	}, 
	{
		title: '鲜花',
		src: 'https://music.163.com/song/media/outer/url?id=2086327879.mp3',
		id: 2086327879,
	},
	{
		title: '水星记',
		src: 'https://music.163.com/song/media/outer/url?id=441491828.mp3',
		id: 441491828,
	}, 
	{
		title: '人生有时候懂得放弃',
		src: 'https://music.163.com/song/media/outer/url?id=2139388989.mp3',
		id: 2139388989,
	},
	{
		title: '精卫',
		src: 'https://music.163.com/song/media/outer/url?id=1951069525.mp3',
		id: 1951069525,
	},
],
}
3.3.3 实现暂停播放、切换音乐

在这里插入图片描述

要实现播放音乐首先要给$AudioContext设置音乐地址src,这样才能通过地址去获取对应的音乐信息。

首选需要在页面一加载时默认配置列表中第一首歌的地址:

onLoad() {
	this.$AudioContext.playbackRate = 2;
	if (this.audioList.length) {
		this.$AudioContext.src = this.audioList[this.currentIndex].src;
		this.currentTitle = this.audioList[this.currentIndex].title;
		this.setPlayInfo();
	}
    // 开始播放获取音乐信息
	this.$AudioContext.onPlay((e) => {
		this.setPlayInfo();
	});
	this.$AudioContext.onEnded((e) => {
		// 结束播放去播放下一首
		this.hanleAudioChange();
	});
},

播放按钮: 判断paused的状态选择性去调用播放和暂停方法;

切换音乐: 点击音乐列表行更新音乐地址src,停止当前音乐,最后调用播放方法即可;

// 音乐播放
handlePlay() {
	this.$AudioContext.paused ? this.$AudioContext.play() : this.$AudioContext.pause();
	this.paused = this.$AudioContext.paused;
	this.recursionDeep();
},
// 选择目标音乐播放
handleCurrentAudio(index) {
	this.currentIndex = index;
	this.currentTitle = this.audioList[index].title;
	// 先停止当前音乐
	this.$AudioContext.stop();
	// 更换播放地址
	this.$AudioContext.src = this.audioList[index].src;
	// 播放音乐
	this.handlePlay();
},
3.3.4 进度条功能实现

首先明确功能点:

  1. 根据音乐播放进度条增加,显示当前播放时长和总时长(可以根据定时任务获取最新音乐播放信息);
  2. 可以拖动选择特定位置播放(通过touchmove与touchend事件监听实现);
  3. 点击某一位置直接跳转对应位置播放(通过点击事件获取x轴位置)
// 递归循环获取最新音乐进度信息
recursionDeep() {
	clearTimeout(this.timer);
	if (this.paused) {
		return
	};
	this.timer = setTimeout(() => {
		if (!this.isMove) {
			this.setPlayInfo();
			this.recursionDeep();
		}
	}, 500)
},
// 进度条点击事件
progressClick(event) {
	const {
		x
	} = event.detail;
	const progressWidth = Math.floor(x / this.progressParentWidth * 100);
	this.playInfo.progressWidth = progressWidth > 100 ? 100 : progressWidth;
	console.log("event", event);
	this.progressMouseDown();
},
// 音乐进度条移动监听
progressMouseMove(event) {
	if (!this.$AudioContext.src) {
		return;
	}
	this.isMove = true;
	const {
		pageX
	} = event.changedTouches[0];
	const progressWidth = Math.floor(pageX / this.progressParentWidth * 100);
	this.playInfo.progressWidth = progressWidth > 100 ? 100 : progressWidth;
},
// 音乐进度条停止监听
progressMouseDown(event) {
	this.isMove = false;
	const currentTime = Math.floor(this.$AudioContext.duration * (this.playInfo.progressWidth / 100));
	this.$AudioContext.seek(currentTime);
	this.setPlayInfo();
	if (!this.$AudioContext.paused) {
		this.$AudioContext.pause();
	}
	this.handlePlay();
},

四、完整源码示例

4.1 示例图

在这里插入图片描述

4.2 main.js入口函数

import App from './App'

import Vue from 'vue'
import './uni.promisify.adaptor'
Vue.config.productionTip = false
App.mpType = 'app'

// 新建音乐对象挂载到原型上
const innerAudioContext = uni.createInnerAudioContext();
// 音乐播放报错监听
innerAudioContext.onError((res) => {
  console.log("音乐播放报错监听", res);
});
// 音乐加载中监听
innerAudioContext.onWaiting((res) => {
  console.log("音乐加载中监听", res);
});
Vue.prototype.$AudioContext = innerAudioContext;


const app = new Vue({
  ...App
})
app.$mount()

4.3 index.vue界面

<template>
	<view class="content">
		<scroll-view class="main-container" scroll-y>
			<view class="line_box" :class="currentIndex === index ? 'line_box bgc_line' : 'line_box'"
				v-for="(item, index) in audioList" :key="item.id" @click="handleCurrentAudio(index)">
				{{item.title}}
			</view>
		</scroll-view>
		<view class="audio_box">
			<view class="current_title" v-show="currentTitle">
				当前播放歌曲:{{currentTitle}}
			</view>

			<view class="music-progress-bar" @click="progressClick">
				<view class="progress-bar-line" :style="{width: playInfo.progressWidth + '%'}" @touchmove="progressMouseMove"
					@touchend="progressMouseDown"></view>
			</view>
			<view class="show_time">
				<view>{{playInfo.currentValue}}</view>
				<view>{{playInfo.durationValue}}</view>
			</view>
			<view class="audio_control">
				<view @click="hanleAudioChange('pre')">上一首</view>
				<view @click="handlePlay">{{ paused ? '播放' : '暂停'}}</view>
				<view @click="hanleAudioChange('next')">下一首</view>
			</view>
		</view>

	</view>
</template>

<script>
	export default {
		data() {
			return {
				timer: null,
				currentTitle: '未完成之前',
				currentIndex: 0,
				paused: true,
				isMove: false,
				playInfo: {
					progressWidth: 2, // 滚动条
					currentTime: 0, // 当前音乐时间s
					currentValue: '00:00', // 转换成时间展示
					duration: 0, // 当前音乐总时间s
					durationValue: '00:00', // 总时间转换展示 
				},
				audioList: [{
						title: '未完成之前',
						src: 'https://music.163.com/song/media/outer/url?id=1453946527.mp3',
						id: 1453946527,
					},
					{
						title: '鲜花',
						src: 'https://music.163.com/song/media/outer/url?id=2086327879.mp3',
						id: 2086327879,
					},
					{
						title: '水星记',
						src: 'https://music.163.com/song/media/outer/url?id=441491828.mp3',
						id: 441491828,
					},
					{
						title: '人生有时候懂得放弃',
						src: 'https://music.163.com/song/media/outer/url?id=2139388989.mp3',
						id: 2139388989,
					},
					{
						title: '精卫',
						src: 'https://music.163.com/song/media/outer/url?id=1951069525.mp3',
						id: 1951069525,
					},
				],
				progressParentWidth: 0,
			}
		},
		onLoad() {
			this.$AudioContext.playbackRate = 2;
			if (this.audioList.length) {
				this.$AudioContext.src = this.audioList[this.currentIndex].src;
				this.currentTitle = this.audioList[this.currentIndex].title;
				this.setPlayInfo();
			}
			this.$AudioContext.onPlay((e) => {
				// 开始播放获取音乐信息
				this.setPlayInfo();
			});
			this.$AudioContext.onEnded((e) => {
				// 结束播放去播放下一首
				this.hanleAudioChange();
			});
		},
		onShow() {
			this.$nextTick(async () => {
				const query = uni.createSelectorQuery().in(this);
				query.select('.music-progress-bar').boundingClientRect(data => {
					this.progressParentWidth = data ? Math.floor(data.width) : 0;
				}).exec();
			});

		},
		onUnload() {
			// 卸载时关闭监听
			this.$AudioContext.offPlay();
			this.$AudioContext.offPlay();
		},
		methods: {
			// 进度条点击事件
			progressClick(event) {
				const {
					x
				} = event.detail;
				const progressWidth = Math.floor(x / this.progressParentWidth * 100);
				this.playInfo.progressWidth = progressWidth > 100 ? 100 : progressWidth;
				console.log("event", event);
				this.progressMouseDown();
			},
			// 音乐进度条移动监听
			progressMouseMove(event) {
				if (!this.$AudioContext.src) {
					return;
				}
				this.isMove = true;
				const {
					pageX
				} = event.changedTouches[0];
				const progressWidth = Math.floor(pageX / this.progressParentWidth * 100);
				this.playInfo.progressWidth = progressWidth > 100 ? 100 : progressWidth;
			},
			// 音乐进度条停止监听
			progressMouseDown(event) {
				this.isMove = false;
				const currentTime = Math.floor(this.$AudioContext.duration * (this.playInfo.progressWidth / 100));
				this.$AudioContext.seek(currentTime);
				this.setPlayInfo();
				if (!this.$AudioContext.paused) {
					this.$AudioContext.pause();
				}
				this.handlePlay();
			},
			// 音乐播放
			handlePlay() {
				this.$AudioContext.paused ? this.$AudioContext.play() : this.$AudioContext.pause();
				this.paused = this.$AudioContext.paused;
				this.recursionDeep();
			},
			// 选择目标音乐播放
			handleCurrentAudio(index) {
				this.currentIndex = index;
				this.currentTitle = this.audioList[index].title;
				// 先停止当前音乐
				this.$AudioContext.stop();
				// 更换播放地址
				this.$AudioContext.src = this.audioList[index].src;
				// 播放音乐
				this.handlePlay();
			},
			// 递归循环获取最新音乐进度信息
			recursionDeep() {
				clearTimeout(this.timer);
				if (this.paused) {
					return
				};
				this.timer = setTimeout(() => {
					if (!this.isMove) {
						this.setPlayInfo();
						this.recursionDeep();
					}
				}, 500)
			},
			// 秒转换为分钟
			secondsToMinutesWithSeconds(seconds) {
				const minutes = Math.floor(seconds / 60);
				const remainingSeconds = Math.floor(seconds % 60);
				return `${this.padZero(minutes)}:${this.padZero(remainingSeconds)}`;
			},
			// 补零
			padZero(number, length = 2) {
				var str = "" + number;
				while (str.length < length) {
					str = "0" + str;
				}
				return str;
			},
			// 设置播放对象
			setPlayInfo() {
				const currentTime = this.$AudioContext.currentTime || 0;
				const duration = this.$AudioContext.duration || 0;
				const progressWidth = duration === 0 ? '2' : Math.floor((currentTime / duration) * 100);
				const currentValue = this.secondsToMinutesWithSeconds(currentTime);
				const durationValue = this.secondsToMinutesWithSeconds(duration);
				this.playInfo = {
					currentTime,
					duration,
					progressWidth,
					currentValue,
					durationValue
				};
			},
			// 切换歌曲
			hanleAudioChange(type = 'next') {
				if (type === 'pre') {
					this.currentIndex = this.currentIndex === 0 ? this.audioList.length - 1 : this.currentIndex - 1;
				} else {
					this.currentIndex = this.currentIndex === this.audioList.length - 1 ? 0 : this.currentIndex + 1;
				};
				this.$AudioContext.src = this.audioList[this.currentIndex].src;
				this.currentTitle = this.audioList[this.currentIndex].title;
				// 播放歌曲
				this.handlePlay();
			},
		}
	}
</script>

<style>
	.content {
		width: 100vw;
		height: calc(100vh - 44px - env(safe-area-inset-top));
		background-color: #1A262D;
		color: #fff;
	}

	.main-container {
		width: 100vw;
		height: 46vh;
	}

	.line_box {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 92%;
		height: 60px;
		border-radius: 8px;
		margin: 10px auto;
		border: 2px solid #eee;
		background-color: aquamarine;
		color: #333;
		font-weight: bold;
	}

	.audio_control {
		display: flex;
		align-items: center;
		justify-content: space-around;
		color: #333;
		margin-top: 40px;
	}

	.audio_control view {
		width: 100px;
		height: 40px;
		text-align: center;
		line-height: 40px;
		background: #edeeab;
		border: 1px solid #eee;
		border-radius: 6px;
	}

	.audio_box {
		width: 90%;

		margin: 30px auto;
	}

	.current_title {
		margin-bottom: 20px;
		font-weight: bold;
		font-size: 18px;
	}

	.bgc_line {
		background-color: #e1964b;
	}

	.show_time {
		width: 100%;
		display: flex;
		justify-content: space-between;
		margin-top: 12rpx;
	}

	// 音乐进度条
	.music-progress-bar {
		position: relative;
		width: 100%;
		height: 6rpx;
		border-radius: 6rpx;
		background-color: #f3e7d9;

		.progress-bar-line {
			position: absolute;
			top: 0%;
			left: 0%;
			width: 2%;
			height: 100%;
			border-radius: 6rpx;
			background-color: #e1964b;
		}

		.progress-bar-line::after {
			content: "";
			display: inline-block;
			position: absolute;
			right: 0%;
			top: 50%;
			transform: translateY(-50%);
			width: 20rpx;
			height: 20rpx;
			background-color: #fff;
			border-radius: 50%;
		}
	}
</style>

4.4 项目源码地址

https://gitee.com/yangdacongming/implementation-of-uniapp-music.git

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学浪app的课程怎么导出来

在这个知识如星辰般璀璨的时代&#xff0c;学浪app汇聚了无数智慧的火花&#xff0c;点亮了求知者的前行之路。你是否曾在学浪的海洋中遨游&#xff0c;汲取知识的甘露&#xff0c;却渴望将那些珍贵的课程内容&#xff0c;如同宝藏一般&#xff0c;从数字的海洋中提取出来&…

PY32F403系列单片机,32位M4内核MCU,主频最高144MHZ

PY32F403系列单片机是基于Arm Cortex-M4核的32位通用微控制器产品。内置的FPU和DSP功能支持浮点运算和全部DSP指令。通过平衡成本&#xff0c;性能&#xff0c;功耗来获得更好的用户体验。 PY32F403单片机典型工作频率可达144MHZ&#xff0c;内置高速存储器&#xff0c;丰富的…

Python-VBA函数之旅-str函数

目录 一、str函数的常见应用场景 二、str函数使用注意事项 三、如何用好str函数&#xff1f; 1、str函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://myelsa1024.blog.csdn.net/ 一、str函数的常…

【C -> Cpp】由C迈向Cpp (5)

标题&#xff1a;【C -> Cpp】由C迈向Cpp&#xff08;5&#xff09; 水墨不写bug &#xff08;图片来源于网络&#xff09; 不抵制失败&#xff0c;携手失败&#xff0c;迈向成功 正文开始&#xff1a; &#xff08;一&#xff09;深入理解构造函数 在之前的讲解中&#x…

安装Ununtu后常见问题(无法远程连接、root密码等)

安装Ununtu后常见问题&#xff08;无法远程连接、root密码、无法ifconfig等&#xff09; 提示&#xff1a;安装完Ununtu系统后会遇到一些常见的问题&#xff0c;本文一次洗解决 文章目录 安装Ununtu后常见问题&#xff08;无法远程连接、root密码、无法ifconfig等&#xff09;一…

Linux(Ubuntu24.04) 安装 MinIO

本文所使用的 Ubuntu 系统版本是 Ubuntu 24.04 ! # 1、下载 MinIO wget https://dl.min.io/server/minio/release/linux-amd64/minio# 2、添加可执行权限 chmod x minio# 3、导出环境变量&#xff0c;用于设置账号密码&#xff0c;我设置的账号和密码都是 minioadmin export MI…

PyQt5中的QtDesigner窗口

文章目录 1. 简介2. QtDesigner的MainWindow2.1 创建MainWindow2.2 添加组件2.3 预览2.4 查看对应的Python代码2.5 保存窗口并命名为login.ui&#xff0c;如下所示2.6对ui文件进行转换得到.py原件 3. 窗口常用属性及说明3.1 设置对象名称3.2 改变标题名字3.3 修改窗口大小 4. 更…

PyCharm 集成 Git

目录 1、配置 Git 忽略文件 2、定位Git 3、使用pycharm本地提交 3.1、初始化本地库 3.2、添加到暂存区 3.3、提交到本地库 3.4、切换版本 4、分支操作 4.1、创建分支 4.2、切换分支 4.3、合并分支 5、解决冲突 1、配置 Git 忽略文件 作用&#xff1a;与项目的实际…

conan2 基础入门(04)-指定编译器(gcc为例)

conan2 基础入门(04)-指定编译器(gcc为例) 文章目录 conan2 基础入门(04)-指定编译器(gcc为例)⭐准备生成profile文件预备文件和Code ⭐使用指令预览正确执行结果可能出现的问题 ⭐具体讲解conancmake ENDsettings.yml ⭐准备 生成profile文件 # 生成默认profile文件&#xf…

【userfaultfd+条件竞争劫持modprobe_path】TSGCTF 2021 -- lkgit

前言 入门题&#xff0c;单纯就是完成每日一道 kernel pwn 的 kpi &#x1f600; 题目分析 内核版本&#xff1a;v5.10.25&#xff0c;可以使用 userfaultfd&#xff0c;不存在 cg 隔离开启了 smap/smep/kaslr/kpti 保护开启了 SLAB_HADNERN/RANDOM 保护 题目给了源码&…

使用IDA自带python patch的一道例题

首先看见就是迷宫 迷宫解出的路径&#xff0c;放在zip的文件可以得到一个硬编码 然后在原程序中&#xff0c;有一处很离谱 这个debugbreak就是IDA分析错误导致的 我们点进去发现里面全是nop 然后我们把我们得到的硬编码放在010里面&#xff0c;再用IDA打开 重新编译看汇编 你…

Python---Numpy万字总结(2)

NumPy的应用&#xff08;2&#xff09; 数组对象的方法 获取描述统计信息 描述统计信息主要包括数据的集中趋势、离散程度和频数分析等&#xff0c;其中集中趋势主要看均值和中位数&#xff0c;离散程度可以看极值、方差、标准差等 array1 np.random.randint(1, 100, 10) …

音视频--AAC编码解析和示例

目录 1&#xff1a;AAC编码介绍 2&#xff1a;AAC格式介绍 3&#xff1a;AAC -ADTS帧组成 4&#xff1a;AAC-ADTS&#xff1a;&#xff08;adts_fixed_header&#xff09;格式介绍 5&#xff1a;AAC-ADTS&#xff1a;&#xff08;adts_variable_header&#xff09;格式介绍…

符合Misra C++标准且支持mmap的内存池管理模块

概述 定义内存管理的相关行为。使用了预分配的管理&#xff0c;先分配一块足够大的内存&#xff0c;然后需要时再从这块内存中进行分配。 代码仓库&#xff1a;https://gitee.com/liudegui/mem_pool 类之间的关系 模块名功能MemPool内存池模块入口&#xff0c;提供常用的模块…

HDFS- DataNode磁盘扩缩容

HDFS- DataNode磁盘扩缩容 背景: 缩减/增加节点磁盘 方案介绍: 采用hdfs dfsadmin -reconfig 动态刷新配置实现,不停服扩缩容。 注意事项: 请在进行缩容之前,务必了解实际的数据量,并确保磁盘有足够的空间来容纳这些数据。还需要考虑未来的使用需求,要预留一定数量的空间…

面向电商家居行业3D室内场景合成中的空间感知

本文主要介绍了3D场景合成技术在电商领域&#xff0c;尤其是家居家装行业的应用。它解释了如何使用3D场景合成创建逼真的室内设计&#xff0c;让消费者能够交互式地查看和体验产品&#xff0c;提高购物的趣味性和效率。文章提到了两种主要的3D室内场景生成算法&#xff1a;传统…

Curator分布式锁

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 分布式锁服务宕机,…

RZ9692实训开发通信系统构建(含配置json配置文件)

实验名称 通信系统的构建 实验目的&#xff1a; 实现一个通信系统的构建&#xff0c;要求传输两路正弦波&#xff0c;和一路视频信号&#xff0c;要求在接受端完整接受正弦信号和视频信号。 一、实验原理&#xff1a; 数字通信系统的一般模型&#xff1a; 数字通信系统的一…

验证搜索二叉树

目录 题目 方法一 思路 优化 方法二 思维误区 递归关系推导 代码实现 题目 98. 验证二叉搜索树 难度&#xff1a;中等 给你一个二叉树的根节点root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含…

Python 开发 框架安全:Django SQL注入漏洞测试.(CVE-2021-35042)

什么是 Django 框架 Django 是一个用 Python 编写的 Web 应用程序框架。它提供了许多工具和库&#xff0c;使得开发 Web 应用程序变得更加容易和高效。Django 遵循了“MTV”&#xff08;模型-模板-视图&#xff09;的设计模式&#xff0c;将应用程序的不同组件分离开来&#x…