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

工程化与框架系列(27)--前端音视频处理

前端音视频处理 🎥

引言

前端音视频处理是现代Web应用中的重要组成部分,涉及音频播放、视频处理、流媒体传输等多个方面。本文将深入探讨前端音视频处理的关键技术和最佳实践,帮助开发者构建高质量的多媒体应用。

音视频技术概述

前端音视频处理主要包括以下技术方向:

  • 音频处理:音频播放、录制、分析
  • 视频处理:视频播放、录制、编辑
  • 流媒体:实时音视频、直播推流
  • WebRTC:点对点通信
  • 媒体格式:编解码、转换

音频处理实现

音频播放器

// 音频播放器类
class AudioPlayer {private audio: HTMLAudioElement;private audioContext: AudioContext;private source: MediaElementAudioSourceNode;private analyser: AnalyserNode;private gainNode: GainNode;private equalizer: EqualizerNode;constructor() {this.audio = new Audio();this.audioContext = new AudioContext();// 创建音频源this.source = this.audioContext.createMediaElementSource(this.audio);// 创建分析器this.analyser = this.audioContext.createAnalyser();this.analyser.fftSize = 2048;// 创建音量控制this.gainNode = this.audioContext.createGain();// 创建均衡器this.equalizer = new EqualizerNode(this.audioContext);// 连接音频节点this.source.connect(this.analyser).connect(this.equalizer.input).connect(this.gainNode).connect(this.audioContext.destination);// 初始化事件监听this.initializeEventListeners();}// 加载音频loadAudio(url: string): Promise<void> {return new Promise((resolve, reject) => {this.audio.src = url;this.audio.load();this.audio.oncanplaythrough = () => resolve();this.audio.onerror = () => reject(new Error('Failed to load audio'));});}// 播放play(): Promise<void> {return this.audio.play();}// 暂停pause(): void {this.audio.pause();}// 跳转到指定时间seek(time: number): void {this.audio.currentTime = time;}// 设置音量setVolume(volume: number): void {this.gainNode.gain.value = Math.max(0, Math.min(1, volume));}// 设置均衡器setEqualizerBand(frequency: number, gain: number): void {this.equalizer.setBand(frequency, gain);}// 获取频谱数据getSpectrumData(): Uint8Array {const dataArray = new Uint8Array(this.analyser.frequencyBinCount);this.analyser.getByteFrequencyData(dataArray);return dataArray;}// 获取波形数据getWaveformData(): Uint8Array {const dataArray = new Uint8Array(this.analyser.frequencyBinCount);this.analyser.getByteTimeDomainData(dataArray);return dataArray;}// 初始化事件监听private initializeEventListeners(): void {// 播放状态变化this.audio.addEventListener('play', () => {this.audioContext.resume();});// 音频结束this.audio.addEventListener('ended', () => {// 处理播放结束});// 音频错误this.audio.addEventListener('error', (e) => {console.error('Audio error:', e);});}
}// 均衡器节点类
class EqualizerNode {private context: AudioContext;private bands: BiquadFilterNode[];private _input: GainNode;private _output: GainNode;constructor(context: AudioContext) {this.context = context;this.bands = [];// 创建输入输出节点this._input = context.createGain();this._output = context.createGain();// 创建均衡器频段this.createBands();// 连接频段this.connectBands();}// 获取输入节点get input(): AudioNode {return this._input;}// 获取输出节点get output(): AudioNode {return this._output;}// 设置频段增益setBand(frequency: number, gain: number): void {const band = this.bands.find(b => Math.abs(b.frequency.value - frequency) < 1);if (band) {band.gain.value = gain;}}// 创建均衡器频段private createBands(): void {const frequencies = [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000];frequencies.forEach(freq => {const filter = this.context.createBiquadFilter();filter.type = 'peaking';filter.frequency.value = freq;filter.Q.value = 1;filter.gain.value = 0;this.bands.push(filter);});}// 连接频段private connectBands(): void {this.bands.reduce((prev, curr) => {prev.connect(curr);return curr;}, this._input);this.bands[this.bands.length - 1].connect(this._output);}
}// 使用示例
const player = new AudioPlayer();// 加载并播放音频
async function playAudio(url: string) {try {await player.loadAudio(url);await player.play();// 设置音量player.setVolume(0.8);// 设置均衡器player.setEqualizerBand(60, 3); // 增强低频player.setEqualizerBand(12000, 2); // 增强高频// 实时更新频谱显示function updateSpectrum() {const spectrumData = player.getSpectrumData();// 使用频谱数据绘制可视化效果requestAnimationFrame(updateSpectrum);}updateSpectrum();} catch (error) {console.error('Failed to play audio:', error);}
}

音频录制器

// 音频录制器类
class AudioRecorder {private stream: MediaStream | null;private mediaRecorder: MediaRecorder | null;private audioChunks: Blob[];private isRecording: boolean;constructor() {this.stream = null;this.mediaRecorder = null;this.audioChunks = [];this.isRecording = false;}// 请求麦克风权限async requestPermission(): Promise<void> {try {this.stream = await navigator.mediaDevices.getUserMedia({audio: true});} catch (error) {throw new Error('Failed to get microphone permission');}}// 开始录制startRecording(): void {if (!this.stream) {throw new Error('No audio stream available');}this.audioChunks = [];this.mediaRecorder = new MediaRecorder(this.stream);this.mediaRecorder.addEventListener('dataavailable', (event) => {if (event.data.size > 0) {this.audioChunks.push(event.data);}});this.mediaRecorder.start();this.isRecording = true;}// 停止录制stopRecording(): Promise<Blob> {return new Promise((resolve, reject) => {if (!this.mediaRecorder || !this.isRecording) {reject(new Error('Not recording'));return;}this.mediaRecorder.addEventListener('stop', () => {const audioBlob = new Blob(this.audioChunks, {type: 'audio/webm'});resolve(audioBlob);});this.mediaRecorder.stop();this.isRecording = false;});}// 暂停录制pauseRecording(): void {if (this.mediaRecorder && this.isRecording) {this.mediaRecorder.pause();}}// 恢复录制resumeRecording(): void {if (this.mediaRecorder && this.isRecording) {this.mediaRecorder.resume();}}// 释放资源dispose(): void {if (this.stream) {this.stream.getTracks().forEach(track => track.stop());this.stream = null;}this.mediaRecorder = null;this.audioChunks = [];this.isRecording = false;}
}// 使用示例
const recorder = new AudioRecorder();async function startRecording() {try {// 请求麦克风权限await recorder.requestPermission();// 开始录制recorder.startRecording();// 5秒后停止录制setTimeout(async () => {const audioBlob = await recorder.stopRecording();// 创建音频URLconst audioUrl = URL.createObjectURL(audioBlob);// 创建音频元素播放录音const audio = new Audio(audioUrl);audio.play();// 清理资源recorder.dispose();}, 5000);} catch (error) {console.error('Recording failed:', error);}
}

视频处理实现

视频播放器

// 视频播放器类
class VideoPlayer {private video: HTMLVideoElement;private canvas: HTMLCanvasElement;private ctx: CanvasRenderingContext2D;private isPlaying: boolean;constructor(videoElement: HTMLVideoElement,canvas: HTMLCanvasElement) {this.video = videoElement;this.canvas = canvas;this.ctx = canvas.getContext('2d')!;this.isPlaying = false;this.initializePlayer();}// 初始化播放器private initializePlayer(): void {// 设置画布尺寸this.canvas.width = this.video.clientWidth;this.canvas.height = this.video.clientHeight;// 监听视频事件this.video.addEventListener('play', () => {this.isPlaying = true;this.render();});this.video.addEventListener('pause', () => {this.isPlaying = false;});this.video.addEventListener('ended', () => {this.isPlaying = false;});}// 加载视频loadVideo(url: string): Promise<void> {return new Promise((resolve, reject) => {this.video.src = url;this.video.load();this.video.oncanplaythrough = () => resolve();this.video.onerror = () => reject(new Error('Failed to load video'));});}// 播放play(): Promise<void> {return this.video.play();}// 暂停pause(): void {this.video.pause();}// 跳转到指定时间seek(time: number): void {this.video.currentTime = time;}// 设置播放速度setPlaybackRate(rate: number): void {this.video.playbackRate = rate;}// 应用滤镜效果applyFilter(filter: VideoFilter): void {this.ctx.filter = filter.toString();}// 渲染视频帧private render(): void {if (!this.isPlaying) return;// 绘制视频帧this.ctx.drawImage(this.video,0,0,this.canvas.width,this.canvas.height);// 继续渲染下一帧requestAnimationFrame(() => this.render());}// 截取当前帧captureFrame(): string {return this.canvas.toDataURL('image/png');}// 导出视频片段async exportClip(startTime: number,endTime: number): Promise<Blob> {const stream = this.canvas.captureStream();const recorder = new MediaRecorder(stream);const chunks: Blob[] = [];recorder.ondataavailable = (e) => {if (e.data.size > 0) {chunks.push(e.data);}};return new Promise((resolve, reject) => {recorder.onstop = () => {const blob = new Blob(chunks, { type: 'video/webm' });resolve(blob);};// 开始录制this.video.currentTime = startTime;recorder.start();// 到达结束时间后停止const checkTime = () => {if (this.video.currentTime >= endTime) {recorder.stop();this.pause();} else {requestAnimationFrame(checkTime);}};this.play().then(checkTime);});}
}// 视频滤镜类
class VideoFilter {private filters: Map<string, number>;constructor() {this.filters = new Map();}// 设置亮度setBrightness(value: number): void {this.filters.set('brightness', value);}// 设置对比度setContrast(value: number): void {this.filters.set('contrast', value);}// 设置饱和度setSaturation(value: number): void {this.filters.set('saturate', value);}// 设置色相setHue(value: number): void {this.filters.set('hue-rotate', value);}// 设置模糊setBlur(value: number): void {this.filters.set('blur', value);}// 转换为CSS滤镜字符串toString(): string {return Array.from(this.filters.entries()).map(([key, value]) => `${key}(${value}${this.getUnit(key)})`).join(' ');}// 获取滤镜单位private getUnit(filter: string): string {switch (filter) {case 'blur':return 'px';case 'hue-rotate':return 'deg';default:return '%';}}
}// 使用示例
const video = document.getElementById('video') as HTMLVideoElement;
const canvas = document.getElementById('canvas') as HTMLCanvasElement;
const player = new VideoPlayer(video, canvas);// 加载并播放视频
async function playVideo(url: string) {try {await player.loadVideo(url);await player.play();// 应用滤镜效果const filter = new VideoFilter();filter.setBrightness(110);filter.setContrast(120);filter.setSaturation(130);player.applyFilter(filter);// 截取当前帧setTimeout(() => {const frameData = player.captureFrame();const img = new Image();img.src = frameData;document.body.appendChild(img);}, 3000);// 导出视频片段setTimeout(async () => {const clip = await player.exportClip(5, 10);const url = URL.createObjectURL(clip);const a = document.createElement('a');a.href = url;a.download = 'clip.webm';a.click();}, 5000);} catch (error) {console.error('Failed to play video:', error);}
}

流媒体处理

WebRTC实现

// WebRTC连接管理器
class WebRTCManager {private peerConnection: RTCPeerConnection;private localStream: MediaStream | null;private remoteStream: MediaStream | null;private dataChannel: RTCDataChannel | null;constructor() {this.peerConnection = new RTCPeerConnection({iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]});this.localStream = null;this.remoteStream = null;this.dataChannel = null;this.initializeConnection();}// 初始化连接private initializeConnection(): void {// 监听ICE候选this.peerConnection.onicecandidate = (event) => {if (event.candidate) {// 发送ICE候选到远端this.sendSignalingMessage({type: 'candidate',candidate: event.candidate});}};// 监听远端流this.peerConnection.ontrack = (event) => {this.remoteStream = event.streams[0];// 触发远端流更新事件this.onRemoteStreamUpdate(this.remoteStream);};// 创建数据通道this.dataChannel = this.peerConnection.createDataChannel('messageChannel');// 监听数据通道事件this.dataChannel.onmessage = (event) => {this.onDataChannelMessage(event.data);};}// 获取本地媒体流async getLocalStream(constraints: MediaStreamConstraints): Promise<MediaStream> {try {this.localStream = await navigator.mediaDevices.getUserMedia(constraints);// 添加本地流到连接this.localStream.getTracks().forEach(track => {if (this.localStream) {this.peerConnection.addTrack(track, this.localStream);}});return this.localStream;} catch (error) {throw new Error('Failed to get local stream');}}// 创建连接请求async createOffer(): Promise<RTCSessionDescriptionInit> {try {const offer = await this.peerConnection.createOffer();await this.peerConnection.setLocalDescription(offer);return offer;} catch (error) {throw new Error('Failed to create offer');}}// 创建连接应答async createAnswer(): Promise<RTCSessionDescriptionInit> {try {const answer = await this.peerConnection.createAnswer();await this.peerConnection.setLocalDescription(answer);return answer;} catch (error) {throw new Error('Failed to create answer');}}// 处理远端描述async handleRemoteDescription(description: RTCSessionDescriptionInit): Promise<void> {try {await this.peerConnection.setRemoteDescription(new RTCSessionDescription(description));if (description.type === 'offer') {const answer = await this.createAnswer();// 发送应答到远端this.sendSignalingMessage({type: 'answer',answer});}} catch (error) {throw new Error('Failed to handle remote description');}}// 处理ICE候选async handleCandidate(candidate: RTCIceCandidate): Promise<void> {try {await this.peerConnection.addIceCandidate(candidate);} catch (error) {throw new Error('Failed to handle ICE candidate');}}// 发送消息sendMessage(message: string): void {if (this.dataChannel && this.dataChannel.readyState === 'open') {this.dataChannel.send(message);}}// 关闭连接close(): void {if (this.localStream) {this.localStream.getTracks().forEach(track => track.stop());}if (this.dataChannel) {this.dataChannel.close();}this.peerConnection.close();}// 发送信令消息(需要实现)private sendSignalingMessage(message: any): void {// 通过信令服务器发送消息}// 远端流更新回调(需要实现)private onRemoteStreamUpdate(stream: MediaStream): void {// 处理远端流更新}// 数据通道消息回调(需要实现)private onDataChannelMessage(message: string): void {// 处理数据通道消息}
}// 使用示例
const rtcManager = new WebRTCManager();// 开始视频通话
async function startVideoCall() {try {// 获取本地媒体流const localStream = await rtcManager.getLocalStream({video: true,audio: true});// 显示本地视频const localVideo = document.getElementById('localVideo') as HTMLVideoElement;localVideo.srcObject = localStream;// 创建连接请求const offer = await rtcManager.createOffer();// 发送offer到远端(通过信令服务器)// ...} catch (error) {console.error('Video call failed:', error);}
}// 处理远端消息
function handleRemoteMessage(message: any) {switch (message.type) {case 'offer':rtcManager.handleRemoteDescription(message.offer);break;case 'answer':rtcManager.handleRemoteDescription(message.answer);break;case 'candidate':rtcManager.handleCandidate(message.candidate);break;}
}

最佳实践与建议

  1. 性能优化

    • 使用适当的编解码格式
    • 实现预加载和缓冲
    • 优化渲染性能
    • 控制内存使用
  2. 用户体验

    • 流畅的播放体验
    • 合适的缓冲策略
    • 清晰的错误提示
    • 友好的控制界面
  3. 兼容性处理

    • 支持多种格式
    • 优雅降级方案
    • 跨浏览器兼容
    • 移动端适配
  4. 安全性考虑

    • 内容加密
    • 权限控制
    • 防盗链措施
    • 数据保护

总结

前端音视频处理需要考虑以下方面:

  1. 选择合适的技术方案
  2. 优化播放性能
  3. 提供良好体验
  4. 保证安全可靠
  5. 处理兼容性

通过合理的技术选型和优化措施,可以构建出高质量的音视频应用。

学习资源

  1. Web Audio API文档
  2. Media Source Extensions指南
  3. WebRTC开发教程
  4. 音视频编解码知识
  5. 流媒体协议规范

如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关文章:

工程化与框架系列(27)--前端音视频处理

前端音视频处理 &#x1f3a5; 引言 前端音视频处理是现代Web应用中的重要组成部分&#xff0c;涉及音频播放、视频处理、流媒体传输等多个方面。本文将深入探讨前端音视频处理的关键技术和最佳实践&#xff0c;帮助开发者构建高质量的多媒体应用。 音视频技术概述 前端音视…...

芋道打包时报错:缺失@unocss插件

在遇到打包时&#xff0c;报这个错误&#xff0c;提示构建失败是因为 ESLint 在加载 unocss 插件时&#xff0c;找不到 unocss/eslint-plugin 模块 解决办法&#xff1a;安装缺失的依赖&#xff1a;保证unocss/eslint-plugin已经被正确安装&#xff0c; 使用以下命令安装&…...

PY32MD320单片机 QFN32封装,内置多功能三相 NN 型预驱。

PY32MD320单片机是普冉半导体的一款电机专用MCU&#xff0c;芯片采用了高性能的 32 位 ARM Cortex-M0 内核&#xff0c;主要用于电机控制。PY32MD320嵌入高达 64 KB Flash 和 8 KB SRAM 存储器&#xff0c;最高工作频率 48 MHz。PY32MD320单片机的工作温度范围为 -40 ~ 105 ℃&…...

深入解析 configService.addListener 使用中的注意事项

在使用 Nacos 的 configService.addListener 方法进行配置监听时&#xff0c;为了确保程序的稳定性、可靠性以及高效性&#xff0c;有诸多注意事项需要我们关注。下面将对这些关键要点进行详细阐述。 一、连接稳定性 1.1 网络连接问题 Nacos 客户端与服务端通过网络进行通信&…...

Windows控制台函数:控制台读取输入函数ReadConsoleA()

目录 什么是 ReadConsoleA&#xff1f; 它长什么样&#xff1f; 怎么用它&#xff1f; 它跟 std::cin 有什么不一样&#xff1f; 注意事项 什么是 ReadConsoleA&#xff1f; ReadConsoleA 是一个 Windows API 函数&#xff0c;用来从控制台读取用户输入。想象一下&#…...

奇安信 2025 年护网蓝队初选笔试题(附答案解析)

&#x1f525; 爆款 CSDN 题库 | 超全护网蓝队笔试真题 | 含详细答案解析 &#x1f525; 熬夜为大家整理了 奇安信 2025 年护网蓝队初选笔试题&#xff0c;&#xff08;关注我我会持续更新&#xff09;涵盖 SQL 注入、Web 安全、渗透测试、二进制安全 等核心知识点&#xff0c;…...

国产编辑器EverEdit - Web预览设置

1 设置-高级-Web预览 1.1 设置说明 选择主菜单工具 -> 设置 -> 常规&#xff0c;在弹出的选项窗口中选择Web预览分类&#xff0c;如下图所示&#xff1a; 1.1.1 本地浏览HTML文件 如果用户只是在本地浏览HTML文件&#xff0c;即直接用浏览器打开HTML文件&#xff0c;确…...

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集 or Set--lower_bound()的解法!!!

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集 题目 并查集解析代码【并查集解】 Set 解法解析lower_bound代码 题目 并查集解析 首先先让所有的f&#xff08;i&#xff09;i&#xff0c;即每个人最开始的祖先都是自己&#xff0c;然后就每一次都让轮到那个数的父亲1&#xff08…...

HTML 编辑器推荐与 VS Code 使用教程

在进行 HTML 编程时&#xff0c;选择一款合适的 HTML 编辑器能极大地提高开发效率。以下为大家推荐几款常用且功能强大的 HTML 编辑器&#xff0c;同时详细介绍如何使用 VS Code 创建和预览 HTML 文件。 一、HTML 编辑器推荐 VS Code&#xff1a;由微软开发&#xff0c;是一款…...

MyBatis增删改查:静态与动态SQL语句拼接及SQL注入问题解析

MyBatis 是一个优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。本文将深入探讨 MyBatis 中的增删改查操作&#xff0c;重点讲解静态与动态 SQL 语句的拼接&#xff0c;并分析 S…...

在运维工作中,Lvs、nginx、haproxy工作原理分别是什么?

在运维工作中&#xff0c;LVS、NGINX和HAProxy都是常用的负载均衡和反向代理工具&#xff0c;它们在高可用性和负载均衡场景中发挥重要作用。以下是其原理和应用场景详解&#xff1a; LVS&#xff08;Linux Virtual Server&#xff09; 工作原理 LVS是基于Linux内核的负载均…...

linux学习(五)(服务器审查,正常运行时间负载,身份验证日志,正在运行的服务,评估可用内存)

服务器审查 在 Linux 中审查服务器的过程包括评估服务器的性能、安全性和配置&#xff0c;以确定需要改进的领域或任何潜在问题。审查的范围可以包括检查安全增强功能、检查日志文件、审查用户帐户、分析服务器的网络配置以及检查其软件版本。 Linux 以其稳定性和安全性而闻名…...

Java在小米SU7 Ultra汽车中的技术赋能

目录 一、智能驾驶“大脑”与实时数据 场景一&#xff1a;海量数据的分布式计算 场景二&#xff1a;实时决策的毫秒级响应 场景三&#xff1a;弹性扩展与容错机制 技术隐喻&#xff1a; 二、车载信息系统&#xff08;IVI&#xff09;的交互 场景一&#xff1a;Android Automo…...

开发环境搭建-02.后端环境搭建-熟悉项目结构

一.后端环境搭建...

js实现pdf文件路径预览和下载

预览 直接浏览器窗口打开默认就是预览 window.open(文件路径)下载 function downloadPDF(url, filename) {fetch(url).then(response > response.blob()).then(blob > {const link document.createElement(a);link.href URL.createObjectURL(blob);link.download fi…...

【RAG】基于向量检索的 RAG (BGE示例)

RAG机器人 结构体 文本向量化: 使用 BGE 模型将文档和查询编码为向量。 &#xff08;BGE 是专为检索任务优化的开源 Embedding 模型&#xff0c;除了本文API调用&#xff0c;也可以通过Hugging Face 本地部署BGE 开源模型&#xff09; 向量检索: 从数据库中找到与查询相关的文…...

Vue源码解析之mustache模板引擎

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…...

python: DDD using postgeSQL and SQL Server

postgreSQL 注意&#xff1a; # psycopg 2 驱动的连接字符串 #engine create_engine(postgresql://post:geovindulocalhost:5433/TechnologyGame) #Session sessionmaker(bindengine)# 使用 psycopg3 驱动的连接字符串 #engine create_engine(postgresqlpsycopg://user:g…...

Python实例:PyMuPDF实现PDF翻译,英文翻译为中文,并按段落创建中文PDF

基于PyMuPDF与百度翻译的PDF翻译处理系统开发:中文乱码解决方案与自动化排版实践 一 、功能预览:将英文翻译为中文后创建的PDF 二、完整代码 from reportlab.lib.pagesizes import letter from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle...

IntelliJ IDEA 2021版创建springboot项目的五种方式

第一种方式&#xff0c;通过https://start.spring.io作为spring Initializr的url来创建项目。 第二种方式&#xff0c;通过https://start.spring.io官网来直接创建springboot项目压缩包&#xff0c;然后导入至我们的idea中。 点击generate后&#xff0c;即可生成压缩包&#xf…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

SpringAI实战:ChatModel智能对话全解

一、引言&#xff1a;Spring AI 与 Chat Model 的核心价值 &#x1f680; 在 Java 生态中集成大模型能力&#xff0c;Spring AI 提供了高效的解决方案 &#x1f916;。其中 Chat Model 作为核心交互组件&#xff0c;通过标准化接口简化了与大语言模型&#xff08;LLM&#xff0…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...