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

鸿蒙实现视频播放功能

目录:

    • 1、鸿蒙视频功能介绍
    • 2、AVPlayer组件实现视频播放
      • 2.1、播放功能的逻辑处理
      • 2.2、页面调用渲染
      • 2.3、缓存播放信息
    • 3、video组件实现视频播放
      • 3.1、鸿蒙官网实现代码
      • 3.2、通过xml布局文件代码实现
        • I. 创建项目
        • II. 定义布局文件
        • III. 实现音频和视频播放功能
        • IV. 音频播放实现
        • V. 视频播放实现

1、鸿蒙视频功能介绍

鸿蒙提供了两种方式实现视频播放功能:

  • 使用video组件实现视频播放
  • 使用AVPlayer组件实现视频播放

2、AVPlayer组件实现视频播放

2.1、播放功能的逻辑处理

import media from '@ohos.multimedia.media'export class VideoAVPlayerClass {// 创建的播放器应该存在我们的工具类上,这样才能被导出使用static player: media.AVPlayer | null = null// 当前播放器播放视频的总时长static duration: number = 0// 当前播放器播放的时长static time: number = 0// 当前播放器是否播放static isPlay: boolean = false// 当前播放器的播放列表static playList: videoItemType[] = []// 当前播放的视频索引static playIndex: number = 0// surfaceID用于播放画面显示,具体的值需要通过XComponent接口获取static surfaceId: string = ''// 播放器上记录上下文static context: Context|null = null// 创建播放器的方法static async init(initParams: InitParams) {// 存储属性SurfaceID,用于设置播放窗口,显示画面VideoAVPlayerClass.surfaceId = initParams.surfaceId// 将上下文 context 存储到播放器类上VideoAVPlayerClass.context = initParams.context// 创建播放器实例VideoAVPlayerClass.player = await media.createAVPlayer()// ----------------------- 事件监听 --------------------------------------------------------------// 用于进度条,监听进度条长度,刷新资源时长VideoAVPlayerClass.avPlayer.on('durationUpdate', (duration: number) => {console.info('AVPlayer state durationUpdate called. current time: ', duration);// 获取视频总时长VideoAVPlayerClass.duration = duration})// 用于进度条,监听进度条当前位置,刷新当前时间VideoAVPlayerClass.avPlayer.on('timeUpdate', (time) =>{console.info('AVPlayer state timeUpdate called. current time: ', time);// 获取当前播放时长VideoAVPlayerClass.time = time// 更新信息到页面VideoAVPlayerClass.updateState()})// 监听seek生效的事件VideoAVPlayerClass.avPlayer.on('seekDone', (seekDoneTime: number) => {console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);VideoAVPlayerClass.avPlayer.play()VideoAVPlayerClass.isPlay = true})// 监听视频播放错误事件,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程VideoAVPlayerClass.avPlayer.on('error', (err) => {console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);// 调用reset重置资源,触发idle状态VideoAVPlayerClass.avPlayer.reset()})// 监听播放状态机AVPlayerState切换的事件VideoAVPlayerClass.avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {switch (state) {// 成功调用reset接口后触发该状态机上报case 'idle':console.info('AVPlayer state idle called.');break// avplayer 设置播放源后触发该状态上报case 'initialized':console.info('AVPlayerstate initialized called.');// 设置显示画面,当播放的资源为纯音频时无需设置VideoAVPlayerClass.avPlayer.surfaceId = VideoAVPlayerClass.surfaceIdbreak// prepare调用成功后上报该状态机case 'prepared':console.info('AVPlayer state prepared called.');break// play成功调用后触发该状态机上报case 'playing':console.info('AVPlayer state playing called.');break// pause成功调用后触发该状态机上报case 'paused':console.info('AVPlayer state paused called.');break// 播放结束后触发该状态机上报case 'completed':console.info('AVPlayer state completed called.');// 当前视频播放完成,自动播放下一个视频哦if (VideoAVPlayerClass.autoPlayList && VideoAVPlayerClass.playIndex < VideoAVPlayerClass.playList.length) {VideoAVPlayerClass.playIndex++VideoAVPlayerClass.playIndex = (VideoAVPlayerClass.playIndex + VideoAVPlayerClass.playList.length) % VideoAVPlayerClass.playList.lengthVideoAVPlayerClass.singlePlay(VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex])VideoAVPlayerClass.isPlay = true} else {VideoAVPlayerClass.isPlay = false// 停止播放VideoAVPlayerClass.avPlayer.stop()}break// stop接口成功调用后触发该状态机上报case 'stopped':console.info('AVPlayer state stopped called.');// 调用reset接口初始化avplayer状态VideoAVPlayerClass.avPlayer.reset()breakcase 'released':console.info('AVPlayer state released called.');break;default:console.info('AVPlayer state unknown called.');break;}})}// 视频播放static async play() {VideoAVPlayerClass.avPlayer.play()VideoAVPlayerClass.isPlay = trueVideoAVPlayerClass.updateState()}// 视频暂停static pause() {VideoAVPlayerClass.avPlayer.pause()VideoAVPlayerClass.isPlay = falseVideoAVPlayerClass.updateState()}// 切换视频static singlePlay(video?: videoItemType) {if (video) {let index = VideoAVPlayerClass.playList.findIndex((item: videoItemType) => item.id === video.id)if (index > -1) {// 当前要播放的视频在播放列表里VideoAVPlayerClass.playIndex = index} else {// 当前要播放的视频不在播放列表里VideoAVPlayerClass.playList.push(video)VideoAVPlayerClass.playIndex = VideoAVPlayerClass.playList.length - 1}}VideoAVPlayerClass.changePlay()}static async changePlay() {// 将播放状态置为闲置await VideoAVPlayerClass.avPlayer.reset()// 重置当前播放时长和视频时长VideoAVPlayerClass.time = 0VideoAVPlayerClass.duration = 0VideoAVPlayerClass.avPlayer.url = VideoAVPlayerClass.playList[VideoAVPlayerClass.playIndex].urlVideoAVPlayerClass.updateState()}// 更新页面状态static async updateState() {const data = {playState: JSON.stringify({duration: VideoAVPlayerClass.duration,time: VideoAVPlayerClass.time,isPlay: VideoAVPlayerClass.isPlay,playIndex: VideoAVPlayerClass.playIndex,playList: VideoAVPlayerClass.playList,})}// 更新页面emitter.emit({eventId: EmitEventType.UPDATE_STATE}, {data})// 存储首选项const preferences:PreferencesClass = new PreferencesClass(VideoAVPlayerClass.context)await preferences.setVideoPlayState(JSON.parse(data.playState))}}

2.2、页面调用渲染

import emitter from '@ohos.events.emitter';
import PlayingAnimation from '../components/PlayingAnimation';
import { EmitEventType } from '../constants/EventContants';
import { VideoListData } from '../constants/VideoConstants';
import { PlayStateType, PlayStateTypeModel } from '../models/playState';
import { videoItemType } from '../models/video';
import { VideoPlayStateType, VideoPlayStateTypeModel } from '../models/videoPlayState';
import { PreferencesClass } from '../utils/PreferencesClass';
import { VideoAVPlayerClass } from '../utils/VideoAVPlayerClass';@Preview
@Component
struct Index {@StateplayState: VideoPlayStateType = new VideoPlayStateTypeModel({} as VideoPlayStateType)xComController: XComponentController = new XComponentController()surfaceId: string = "" // 定义surfaceIdvideoList: videoItemType[] = VideoListDataasync aboutToAppear() {// 从播放器订阅数据emitter.on({ eventId: EmitEventType.UPDATE_STATE }, (data) => {this.playState = new VideoPlayStateTypeModel(JSON.parse(data.data.playState))})// 从首选项加载数据const preferences:PreferencesClass = new PreferencesClass(getContext(this))this.playState = await preferences.getVideoPlayState()}aboutToDisappear(){// 销毁播放器VideoAVPlayerClass.avPlayer.release()}// 时长数字(ms)转字符串number2time(number: number) {if (!number) {return '00:00'}const ms: number = number % 1000const second = (number - ms) / 1000const s: number = second % 60if (second > 60) {const m: number = (second - s) / 60 % 60return m.toString().padStart(2, '0') + ':' + s.toString().padStart(2, '0')}return '00:' + s.toString().padStart(2, '0')}build() {Row() {Column({ space: 10 }) {Stack() {Column() {Row(){// 视频播放窗口XComponent({id: 'videoXComponent',type: 'surface',controller: this.xComController}).width('100%').height(200).onLoad(async () => {this.xComController.setXComponentSurfaceSize({ surfaceWidth: 1080, surfaceHeight: 1920 });this.surfaceId = this.xComController.getXComponentSurfaceId()if (this.surfaceId) {await VideoAVPlayerClass.init({surfaceId: this.surfaceId, playList: this.videoList, context: getContext(this)})await VideoAVPlayerClass.singlePlay()}})}.onClick(() => {this.playState.isPlay ? VideoAVPlayerClass.pause() : VideoAVPlayerClass.play()})// 进度条Row({space: 6}){// 当前播放时长Text(this.number2time(this.playState?.time)).fontColor($r('app.color.white')).visibility(this.playState?.duration ? Visibility.Visible : Visibility.Hidden)// 进度条Slider({value: this.playState.time,min: 0,max: this.playState.duration,}).trackColor($r('app.color.white')).onChange((value: number, mode: SliderChangeMode) => {// 切换播放进度VideoAVPlayerClass.seekTime(value)}).width("70%")// 视频总时长Text(this.number2time(this.playState?.duration)).fontColor($r('app.color.white')).visibility(this.playState?.duration ? Visibility.Visible : Visibility.Hidden)}.width('100%').height(20).margin({top: 10}).justifyContent(FlexAlign.Center)}.width('100%').height(270).padding({top: 30,bottom:30}).backgroundColor($r('app.color.black')).justifyContent(FlexAlign.Start)// 播放按钮if (!this.playState.isPlay) {Image($r('app.media.ic_play')).width(48).height(48).fillColor($r('app.color.white')).onClick(() => {VideoAVPlayerClass.play()})}}// 视频列表缩略图List({ space: 10, initialIndex: 0 }) {ForEach(this.videoList, (item: videoItemType, index: number) => {ListItem() {Stack({alignContent: Alignment.Center}){Image(item.imgUrl).width(100).height(80)// .objectFit(ImageFit.Contain)if (this.playState.playIndex === index) {Row(){PlayingAnimation({ recordIng: true })}}}}.width(100).onClick(() => {VideoAVPlayerClass.singlePlay(item)})}, item => item)}.height(100).listDirection(Axis.Horizontal) // 排列方向.edgeEffect(EdgeEffect.Spring) // 滑动到边缘无效果.onScrollIndex((firstIndex: number, lastIndex: number) => {console.info('first' + firstIndex)console.info('last' + lastIndex)})}.width('100%').height('100%')}.height('100%').width('100%')}
}export default Index

2.3、缓存播放信息

问题场景:
我们的播放器已经可以正常进行视频的播放和切换了,当我们不小心退出了当前页面,再进入播放页面时,你会发现我们当前播放的视频信息没有了,这是为什么呢?

在当前的实现中,播放页面的信息是通过订阅播放器得到的,如果不播放了,就没有了信息来源的渠道,所以页面的播放信息就没有了。因此我们需要再建立一个信息收集渠道,即使不在播放时,也能获取到最后的播放信息数据。为此,我们使用**@ohos.data.preferences(用户首选项)**来持久化播放信息。

实现一个存储和读取首选项的工具类:

import preferences from '@ohos.data.preferences'
import { videoDefaultState, VideoPlayStateType } from '../models/videoPlayState'export class PreferencesClass {StoreName = 'VIDEO_PLAYER'context: ContextVideoPlayStateKey = "VIDEO_PLAY_STATE"constructor(context: Context) {this.context = context}// 获取storeasync getStore() {return await preferences.getPreferences(this.context,this.StoreName)}// 存储视频播放状态async setVideoPlayState(playState:VideoPlayStateType){const store = await this.getStore()await store.put(this.PlayStateKey,JSON.stringify(playState))await store.flush()}// 读取视频播放状态async getVideoPlayState(): Promise<VideoPlayStateType> {const store = await this.getStore()return JSON.parse(await store.get(this.VideoPlayStateKey,JSON.stringify(videoDefaultState)) as string) as VideoPlayStateType}
}

3、video组件实现视频播放

3.1、鸿蒙官网实现代码

// xxx.ets
@Entry
@Component
struct VideoCreateComponent {@State videoSrc: Resource = $rawfile('video1.mp4')@State previewUri: Resource = $r('app.media.poster1')@State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X@State isAutoPlay: boolean = false@State showControls: boolean = truecontroller: VideoController = new VideoController()build() {Column() {Video({src: this.videoSrc,previewUri: this.previewUri,currentProgressRate: this.curRate,controller: this.controller}).width('100%').height(600).autoPlay(this.isAutoPlay).controls(this.showControls).onStart(() => {console.info('onStart')}).onPause(() => {console.info('onPause')}).onFinish(() => {console.info('onFinish')}).onError(() => {console.info('onError')}).onStop(() => {console.info('onStop')}).onPrepared((e?: DurationObject) => {if (e != undefined) {console.info('onPrepared is ' + e.duration)}}).onSeeking((e?: TimeObject) => {if (e != undefined) {console.info('onSeeking is ' + e.time)}}).onSeeked((e?: TimeObject) => {if (e != undefined) {console.info('onSeeked is ' + e.time)}}).onUpdate((e?: TimeObject) => {if (e != undefined) {console.info('onUpdate is ' + e.time)}})Row() {Button('src').onClick(() => {this.videoSrc = $rawfile('video2.mp4') // 切换视频源}).margin(5)Button('previewUri').onClick(() => {this.previewUri = $r('app.media.poster2') // 切换视频预览海报}).margin(5)Button('controls').onClick(() => {this.showControls = !this.showControls // 切换是否显示视频控制栏}).margin(5)}Row() {Button('start').onClick(() => {this.controller.start() // 开始播放}).margin(2)Button('pause').onClick(() => {this.controller.pause() // 暂停播放}).margin(2)Button('stop').onClick(() => {this.controller.stop() // 结束播放}).margin(2)Button('reset').onClick(() => {this.controller.reset() // 重置AVPlayer}).margin(2)Button('setTime').onClick(() => {this.controller.setCurrentTime(10, SeekMode.Accurate) // 精准跳转到视频的10s位置}).margin(2)}Row() {Button('rate 0.75').onClick(() => {this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // 0.75倍速播放}).margin(5)Button('rate 1').onClick(() => {this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // 原倍速播放}).margin(5)Button('rate 2').onClick(() => {this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // 2倍速播放}).margin(5)}}}
}interface DurationObject {duration: number;
}interface TimeObject {time: number;
}

3.2、通过xml布局文件代码实现

实现步骤:

I. 创建项目

打开 DevEco Studio,创建一个新的 HarmonyOS 项目,选择“Empty Ability”模板。

配置权限:

在项目的配置文件 config.json 中,添加存储权限。

 {"module": {"reqPermissions": [{"name": "ohos.permission.READ_STORAGE"},{"name": "ohos.permission.WRITE_STORAGE"}]}}
II. 定义布局文件

定义布局文件:

在 src/main/resources/base/layout 目录下,创建一个布局文件 ability_main.xml,用于展示音频播放和视频播放的控件。

<?xml version="1.0" encoding="utf-8"?><DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:width="match_parent"ohos:height="match_parent"ohos:orientation="vertical"ohos:padding="16vp"><Videoohos:id="$+id/video_player"ohos:width="match_parent"ohos:height="200vp"ohos:layout_marginBottom="16vp"ohos:scale_type="centerCrop"/><Buttonohos:id="$+id/button_play_video"ohos:width="match_content"ohos:height="wrap_content"ohos:text="Play Video"/><Buttonohos:id="$+id/button_play_audio"ohos:width="match_content"ohos:height="wrap_content"ohos:text="Play Audio"/></DirectionalLayout>
III. 实现音频和视频播放功能

编写 MainAbilitySlice.java:

在 src/main/java/com/example/media/slice 目录下,创建一个 MainAbilitySlice.java 文件,实现音频和视频播放功能。

package com.example.media.slice;import ohos.aafwk.ability.AbilitySlice;import ohos.aafwk.content.Intent;import ohos.agp.components.Button;import ohos.agp.components.Video;import ohos.agp.components.Component;import ohos.media.audio.AudioPlayer;import ohos.media.audio.AudioManager;import ohos.media.audio.AudioStreamType;import ohos.media.audio.AudioSourceType;import ohos.media.audio.AudioFormat;import ohos.media.audio.AudioAttributes;import ohos.media.audio.AudioAttributes.Builder;import ohos.media.audio.AudioTrack;import ohos.media.audio.AudioStream;import ohos.media.audio.AudioTrackCallback;import ohos.media.audio.AudioData;import ohos.media.audio.AudioDataCallback;import ohos.media.audio.AudioManager;import ohos.media.audio.AudioStream;import ohos.media.audio.AudioTrack;import ohos.media.audio.AudioTrackCallback;import ohos.media.audio.AudioTrackCallback;import ohos.media.audio.AudioFormat;import ohos.media.audio.AudioData;import ohos.media.audio.AudioStream;import ohos.media.audio.AudioTrack;import ohos.media.audio.AudioTrackCallback;import ohos.media.audio.AudioTrackCallback;import java.io.IOException;import java.io.InputStream;import java.io.File;import java.io.FileInputStream;//有的写成public class MyAbility extends Ability也是可行的​public class MainAbilitySlice extends AbilitySlice {private Video videoPlayer;private Button buttonPlayVideo;private Button buttonPlayAudio;private AudioPlayer audioPlayer;@Overridepublic void onStart(Intent intent) {//这两步关键,鸿蒙无法直接展示xml布局文件,需要通过父类Ability来加载xml布局文件super.onStart(intent);super.setUIContent(ResourceTable.Layout_ability_main);​videoPlayer = (Video) findComponentById(ResourceTable.Id_video_player);buttonPlayVideo = (Button) findComponentById(ResourceTable.Id_button_play_video);buttonPlayAudio = (Button) findComponentById(ResourceTable.Id_button_play_audio);​buttonPlayVideo.setClickedListener(component -> playVideo());buttonPlayAudio.setClickedListener(component -> playAudio());}private void playVideo() {String videoPath = "path_to_video.mp4";  // Update with actual video pathvideoPlayer.setVideoPath(videoPath);videoPlayer.start();}private void playAudio() {String audioPath = "path_to_audio.mp3";  // Update with actual audio pathaudioPlayer = new AudioPlayer();audioPlayer.setAudioPath(audioPath);audioPlayer.setStreamType(AudioStreamType.MUSIC);audioPlayer.prepare();audioPlayer.start();}@Overridepublic void onStop() {super.onStop();if (audioPlayer != null) {audioPlayer.stop();audioPlayer.release();}}}

代码详细解释

IV. 音频播放实现

初始化 AudioPlayer:

在 playAudio() 方法中,我们首先创建一个 AudioPlayer 实例,设置音频文件路径,指定音频流类型为 MUSIC,并准备和开始播放音频。

 private void playAudio() {String audioPath = "path_to_audio.mp3";  // Update with actual audio pathaudioPlayer = new AudioPlayer();audioPlayer.setAudioPath(audioPath);audioPlayer.setStreamType(AudioStreamType.MUSIC);audioPlayer.prepare();audioPlayer.start();}

资源管理:

在 onStop() 方法中,我们停止并释放 AudioPlayer 实例,确保系统资源被正确释放。

 @Overridepublic void onStop() {super.onStop();if (audioPlayer != null) {audioPlayer.stop();audioPlayer.release();}}
V. 视频播放实现

初始化 Video 组件:

在 playVideo() 方法中,我们设置视频路径,并调用 start() 方法开始播放视频。

 private void playVideo() {String videoPath = "path_to_video.mp4";  // Update with actual video pathvideoPlayer.setVideoPath(videoPath);videoPlayer.start();}

更新布局:

在布局文件中定义 Video 组件用于展示视频内容,确保视频播放界面能够正确显示。

 <Videoohos:id="$+id/video_player"ohos:width="match_parent"ohos:height="200vp"ohos:layout_marginBottom="16vp"ohos:scale_type="centerCrop"/>

相关文章:

鸿蒙实现视频播放功能

目录&#xff1a; 1、鸿蒙视频功能介绍2、AVPlayer组件实现视频播放2.1、播放功能的逻辑处理2.2、页面调用渲染2.3、缓存播放信息 3、video组件实现视频播放3.1、鸿蒙官网实现代码3.2、通过xml布局文件代码实现I. 创建项目II. 定义布局文件III. 实现音频和视频播放功能IV. 音频…...

RabbitMQ介绍及安装

文章目录 一. MQ二. RabbitMQ三. RabbitMQ作用四. MQ产品对比五. 安装RabbitMQ1. 安装erlang2. 安装rabbitMQ3. 安装RabbitMQ管理界⾯4. 启动服务5. 访问界面6. 添加管理员用户7. 重新登录 一. MQ MQ( Message queue ), 从字⾯意思上看, 本质是个队列, FIFO 先⼊先出&#xff…...

第五节、电机多段运动【51单片机-TB6600驱动器-步进电机教程】

摘要&#xff1a;本节介绍用控制步进电机三个主要参数角度、速度、方向&#xff0c;实现简单的步进电机多段控制 一、目标功能 输入多个目标角度&#xff0c;设定好步进电机速度&#xff0c;实现步进电机多段转动 二、计算过程 2.1 速度计算 根据第三节内容&#xff0c;定时器…...

docker run 设置启动命令

在使用 docker run 命令时&#xff0c;你可以通过指定启动命令来覆盖 Docker 镜像中的默认入口点或命令。具体来说&#xff0c;你可以通过以下两种方式来设置启动命令&#xff1a; 覆盖 CMD&#xff1a; 你可以通过在 docker run 命令的最后部分提供命令来覆盖镜像的默认 CMD 指…...

嵌入式蓝桥杯学习拓展 LCD翻转显示

通过配置SS和GS两个标志位&#xff0c;实现扫描方向的切换。 将lcd.c的REG_932X_Init函数进行部分修改。 将LCD_WriteReg(R1, 0x0000);修改为LCD_WriteReg(R1,0x0100); 将LCD_WriteReg(R96, 0x2700); 修改为LCD_WriteReg(R96, 0xA700); void REG_932X_Init1(void) {LCD_Wr…...

SQLite 语法

SQLite 语法 SQLite 是一种轻量级的数据库管理系统&#xff0c;它遵循 SQL&#xff08;结构化查询语言&#xff09;标准。SQLite 的语法相对简单&#xff0c;易于学习和使用。本文将详细介绍 SQLite 的基本语法&#xff0c;包括数据库的创建、表的创建、数据的插入、查询、更新…...

ZLMediaKit+wvp (ffmpeg+obs)推拉流测试

这里使用了两种方式: ffmpeg命令和 OBS OBS推流在网上找了些基本没有说明白的, 在ZLMediaKit的issues中看到了一个好大哥的提问在此记录一下 使用OBS推流&#xff0c;rtmp&#xff0c;报鉴权失败 推流 1. ffmpeg命令推流 官方说明文档地址: 推流规则 rtsp://192.168.1.4:10554…...

【开源免费】基于SpringBoot+Vue.JS高校学科竞赛平台(JAVA毕业设计)

博主说明&#xff1a;本文项目编号 T 075 &#xff0c;文末自助获取源码 \color{red}{T075&#xff0c;文末自助获取源码} T075&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…...

lvgl9 Line(lv_line) 控件使用指南

文章目录 前言主体1. **Line 控件概述**2. **使用场景**3. **控件的样式**4. **设置点**5. **自动大小**6. **y 坐标反转**7. **事件处理**8. **示例代码** 总结 前言 在图形界面设计中&#xff0c;直线绘制是非常常见且重要的功能之一&#xff0c;尤其是在需要进行图形表示、…...

EasyAnimateV5 视频生成大模型原理详解与模型使用

在数字内容创作中&#xff0c;视频扮演的角色日益重要。然而&#xff0c;创作高质量视频通常耗时且昂贵。EasyAnimate 系列旨在利用人工智能技术简化这一过程。EasyAnimateV5 建立在其前代版本的基础之上&#xff0c;不仅在质量上有所提升&#xff0c;还在多模态数据处理和跨语…...

【Copilot 】TAB keybinding not working on JetBrains Client

pycharm ssh 远程到ubuntu24.04 发现tab就是tab,无法输出copilot给出的自动补全到便捷器里。禁用host的copilot插件,重新启动ide就好了。解决办法 参考大神的办法删除主机和客户端插件中的 Copilot插件。 仅在客户端中重新安装 Copilot 插件。 我只是禁用也可以 对比了键盘映…...

leetcode刷题——二叉树(1)

目录 1、递归遍历二叉树 2、迭代法遍历二叉树&#xff08;通过while循环&#xff09; 3、二叉树的层序遍历 4、二叉树的层次遍历 II 5、二叉树的右视图 6、二叉树的层平均值 7、N叉树的层序遍历 8、在每个树行中找最大值 9、填充每个节点的下一个右侧节点指针 10、填…...

HTML5教程-表格宽度设置,最大宽度,自动宽度

HTML表格宽度 参考&#xff1a;html table width HTML表格是网页设计中常用的元素之一&#xff0c;可以用来展示数据、创建布局等。表格的宽度是一个重要的参数&#xff0c;可以通过不同的方式来设置表格的宽度&#xff0c;本文将详细介绍HTML表格宽度的不同设置方式和示例代…...

【计算机网络】 —— 数据链路层(壹)

文章目录 前言 一、概述 1. 基本概念 2. 数据链路层的三个主要问题 二、封装成帧 1. 概念 2. 帧头、帧尾的作用 3. 透明传输 4. 提高效率 三、差错检测 1. 概念 2. 奇偶校验 3. 循环冗余校验CRC 1. 步骤 2. 生成多项式 3. 例题 4. 总结 四、可靠传输 1. 基本…...

力扣-图论-4【算法学习day.54】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非…...

WiFi受限不再愁,电脑无网络快速修复指南

有时在试图连接WiFi时&#xff0c;会发现网络连接受限&#xff0c;或无法正常访问互联网。这种情况不仅影响了工作效率&#xff0c;还可能错过重要的信息。那么&#xff0c;究竟是什么原因导致了电脑WiFi连接受限呢&#xff1f;又该如何解决这一问题呢&#xff1f;小A今天就来教…...

《Java异常处理》

目录 一、异常的概念与分类 二、异常处理机制 三、异常的抛出 四、自定义异常 五、异常处理的最佳实践 在 Java 编程中&#xff0c;异常处理是保障程序健壮性和稳定性的关键环节。有效地处理异常能够避免程序因错误而崩溃&#xff0c;同时提供友好的错误提示信息&#xff…...

清风数学建模学习笔记——Topsis法

数模评价类&#xff08;2&#xff09;——Topsis法 概述 Topsis:Technique for Order Preference by Similarity to Ideal Solution 也称优劣解距离法&#xff0c;该方法的基本思想是&#xff0c;通过计算每个备选方案与理想解和负理想解之间的距离&#xff0c;从而评估每个…...

JVM 面试题

Java 虚拟机&#xff08;JVM&#xff09;是运行 Java 程序的引擎&#xff0c;它是 Java 语言 “一次编译&#xff0c;处处运行” 的核心技术。JVM 的主要任务是将 Java 字节码&#xff08;Bytecode&#xff09;解释成机器码并执行&#xff0c;负责内存管理、线程管理、垃圾回收…...

C语言蓝桥杯2023年省赛真题

文章目录 持续更新中...第一题题目描述输入格式输出格式样例输出提示 2 第二题题目描述 第三题题目描述输入格式输出格式样例输入样例输出 第四题题目描述输入格式输出格式样例输入样例输出提示 第四题题目描述输入格式输出格式样例输入样例输出提示 第五题题目描述输入格式输出…...

Flume基础概念

目录 作用组件构成ClientFlowAgentSourceSinkEvent 和Log4j的区别与定位事务传出流程输入到sourcesource端输入Channel 接收输入到SinkSink输出 作用 Flume可以从各种来源&#xff08;如日志文件、消息队列、网络数据、文件系统、数据库等&#xff09;收集数据&#xff0c;并将…...

哈希处理海量数据

接下来我们将以问题的形式来介绍如何用hash处理海量数据。 1.问题1 &#xff08;位图&#xff09; 给定100亿个整数&#xff0c;设计算法找到只出现一次的。 1.1问题分析 100亿个整数&#xff0c;一个整数占用4byte&#xff0c;那么就需要约40G左右的空间来存储。显然常见的…...

Go语言基础教程1

Go语言基础教程 目录 变量声明与使用基本数据类型常量切片操作字符串处理指针格式化输出参数 一、变量声明 1.1 基本变量声明 // 标准声明 var variableName variableType// 示例 var age int var name string1.2 变量声明与初始化 // 显式类型声明 var age int 30// 类…...

【每日一道面试题】for与foreach的区别(2024/12/6)

目录 foreach的特点遍历时删除时 foreach 和 for循环遍历数组的差别关于 foreach 和 for 循环的效率问题 首先我们要对foreach有个基本的了解&#xff0c;才能对它们进行区别 foreach的特点 遍历时 用foreach循环去遍历一个数组&#xff0c; 用foreach循环去遍历一个集合&…...

解密时序数据库的未来:TDengine Open Day技术沙龙精彩回顾

在数字化时代&#xff0c;开源已成为推动技术创新和知识共享的核心力量&#xff0c;尤其在数据领域&#xff0c;开源技术的涌现不仅促进了行业的快速发展&#xff0c;也让更多的开发者和技术爱好者得以参与其中。随着物联网、工业互联网等技术的广泛应用&#xff0c;时序数据库…...

React第十一节 组件之间通讯之发布订阅模式(自定义发布订阅器)

组件之间通讯常用方案 1、通过props 2、通过context 3、通过发布订阅模式 4、通过Redux 后面会有专栏介绍 什么情况下使用发布订阅模式 a、当我们想要兄弟组件之间通讯&#xff0c;而共同的父组件中又用不到这些数据时候&#xff1b; b、当多个毫无相关的组件之间想要进行数据…...

Vue 2与Vue 3项目中的屏幕缩放适配:使用vue2-scale-box和vue3-scale-box

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…...

Brain.js(九):LSTMTimeStep 实战教程 - 未来短期内的股市指数预测 - 实操要谨慎

系列的前一文RNNTimeStep 实战教程 - 股票价格预测 讲述了如何使用RNN时间序列预测实时的股价&#xff0c; 在这一节中&#xff0c;我们将深入学习如何利用 JavaScript 在浏览器环境下使用 LSTMTimeStep 进行股市指数的短期预测。通过本次实战教程&#xff0c;你将了解到如何用…...

云计算考试题

1、与SaaS不同的,这种“云”计算形式把开发环境或者运行平台也作为一种服务给用户提供。(B) A、软件即服务 B、基于平台服务 C、基于WEB服务 D、基于管理服务 2、云计算是对(D)技术的发展与运用 A、并行计算 B、网格计算 C、分布式计算 D、三个选项都是 3、Amazon.com公司…...

【设计模式】装饰器模式 在java中的应用

文章目录 1. 引言装饰器模式的定义与设计目的装饰器模式与其他设计模式的比较 2. 装饰器模式的结构组件接口&#xff08;Component&#xff09;具体组件&#xff08;ConcreteComponent&#xff09;装饰角色&#xff08;Decorator&#xff09;具体装饰类&#xff08;ConcreteDec…...

【kafka】生产者的同步发送和异步发送

Kafka 的生产者端提供了同步发送和异步发送两种方式&#xff0c;适合不同的使用场景和性能需求。 以下是两种发送模式的详细讲解&#xff1a; 同步发送 概念 同步发送是指生产者在发送一条消息后&#xff0c;会阻塞当前线程&#xff0c;等待 Kafka 返回发送结果&#xff08;…...

8. Debian系统中显示屏免密码自动登录

本文介绍如何在Debian系统上&#xff0c;启动后&#xff0c;自动免密登录&#xff0c;不卡在登录界面。 1. 修改lightDM配置文件 嵌入式Debian系统采用lightDM显示管理器&#xff0c;所以&#xff0c;一般需要修改它的配置文件/etc/lightdm/lightdm.conf&#xff0c;找到[Seat…...

SpringBoot 开源停车场管理收费系统

一、下载项目文件 下载源码项目文件口令&#xff1a; 【前端小程序地址】(3.0)&#xff1a;伏脂火器白泽知洞座/~6f8d356LNL~:/【后台管理地址】(3.0)&#xff1a;伏脂火器仇恨篆洞座/~0f4a356Ks2~:/【岗亭端地址】(3.0)&#xff1a;动作火器智汇堂多好/~dd69356K6r~:/复制口令…...

QT的ui界面显示不全问题(适应高分辨率屏幕)

//自动适应高分辨率 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);一、问题 电脑分辨率高&#xff0c;默认情况下&#xff0c;打开QT的ui界面&#xff0c;显示不全按钮内容 二、解决方案 如果自己的电脑分辨率较高&#xff0c;可以尝试以下方案&#xff1a;自…...

双向链表的模拟实现 —— LinkedList

MyLinkedList类 public class MyLinkedList {// 定义节点类static class Node {int val;Node prev;Node next;public Node() {}public Node(int val) {this.val val;}}// 定义头节点private Node head;// 定义尾结点private Node tail;// 头插public void headInsert(int val…...

速盾:高防cdn预热指定url就只刷新这个吗?

高防CDN预热是指在网站上线或更新之前&#xff0c;将网站内容缓存到CDN节点服务器上&#xff0c;以提高用户访问网站的速度和稳定性。通常&#xff0c;预热可以通过指定URL来进行&#xff0c;而不是刷新整个网站。 预热指定URL的好处是可以选择性地进行缓存刷新&#xff0c;而…...

JDK21新特性

目录 虚拟线程&#xff08;JEP 444&#xff09;&#xff1a; 顺序集合&#xff08;JEP 431&#xff09;&#xff1a; 字符串模板&#xff08;JEP 430&#xff09;&#xff1a; 模式匹配的增强&#xff08;JEP 440、441以及443&#xff09;&#xff1a; 结构化并发和作用域值…...

json学习

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;也易于机器解析和生成。它通常用于在服务器和客户端之间交换数据&#xff0c;特别是在 Web 应用中。 JSON 格式基于 JavaScript 对象表示法&#…...

005-mysql常用的名称

语言分类 DDL &#xff1a;数据定义语言 1、线上DDL语句在对表操作&#xff0c;是要锁元数据表的&#xff0c;此时所有的修改类的命令无法正常运行。 2、对大表在高峰期进行DDL操作&#xff0c;可以使用工具&#xff1a;pt-online-schema-change gh-ost 工具&#xff08;8.0以…...

PostgreSQL和MySQL区别

PostgreSQL 和 MySQL 有以下一些主要区别&#xff1a; 一、功能特性 1. 数据类型支持 - PostgreSQL&#xff1a;支持丰富的数据类型&#xff0c;包括数组、JSON、JSONB、hstore&#xff08;键值对存储&#xff09;、范围类型等。例如&#xff0c;可以直接在数据库中存储和查…...

Android笔记(三十四):onCreate执行Handler.post在onResume后才能执行?

背景 偶然发现一个点&#xff0c;就是在onCreate执行Handler.post在onResume后才执行&#xff0c;以下是测试代码 多次运行的结果一致&#xff0c;为什么execute runnable不是在onCreate和onResume之间执行的呢&#xff0c;带着疑问撸了一遍Activity启动流程 关键源码分析 …...

动手学深度学习d2l包M4芯片 gpu加速

conda创建环境 CONDA_SUBDIRosx-arm64 conda create -n ml python3.9 -c conda-forge conda env config vars set CONDA_SUBDIRosx-arm64 conda activate mlpip安装包 pip install --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/n…...

游戏引擎学习第35天

开场介绍 今天的任务是继续改进一个虚拟的瓦片地图系统&#xff0c;使其适合处理更大的世界。我们希望这个系统能管理大范围的游戏世界&#xff0c;其中包含按需存储的小区域。昨天&#xff0c;我们介绍了“内存区域”的概念&#xff0c;用于管理持久性存储。我们计划今天继续…...

Python 3 和 MongoDB 的集成使用

Python 3 和 MongoDB 的集成使用 MongoDB 是一个流行的 NoSQL 数据库&#xff0c;以其灵活的数据模型和强大的查询功能而闻名。Python 3 作为一种广泛使用的编程语言&#xff0c;与 MongoDB 的集成变得日益重要。本文将介绍如何在 Python 3 环境中集成和使用 MongoDB&#xff…...

MperReduce学习笔记下

自定义InputFormat合并小文件 案例需求 无论hdfs还是mapreduce&#xff0c;对于小文件都有损效率&#xff0c;实践中&#xff0c;又难免面临处理大量小文件的场景&#xff0c;此时&#xff0c;就需要有相应解决方案。 案例分析 小文件的优化无非以下几种方式&#xff1a; …...

react + antd desgin 使用form功能时upload,radio,checkbox不能回显的问题

最近使用react开发 遇到form回显的问题 &#xff0c;处理upload回显的问题&#xff0c;提示 react-refresh:160 Warning: [antd: Upload] value is not a valid prop, do you mean fileList? 查看文档后&#xff0c;在form.item 组件下有一个特殊属性 valuePropName 子节点的值…...

【NLP修炼系列之Bert】Bert多分类多标签文本分类实战(附源码下载)

引言 今天我们就要用Bert做项目实战&#xff0c;实现文本多分类任务和我在实际公司业务中的多标签文本分类任务。通过本篇文章&#xff0c;可以让想实际入手Bert的NLP学习者迅速上手Bert实战项目。 1 项目介绍 本文是Bert文本多分类和多标签文本分类实战&#xff0c;其中多分…...

OpenSSL 自建CA 以及颁发证书(网站部署https双向认证)

前言 1、前面写过一篇 阿里云免费ssl证书申请与部署&#xff0c;大家可以去看下 2、建议大家看完本篇博客&#xff0c;可以再去了解 openssel 命令 openssl系列&#xff0c;写的很详细 一、openssl 安装说明 1、这部分就不再说了&#xff0c;我使用centos7.9&#xff0c;是自…...

YOLOv11改进,YOLOv11添加U-Netv2分割网络中SDI信息融合模块,助力小目标检测

摘要 理论介绍 SDI模块的架构: 平滑卷积(SmoothConv):用于平滑特征图,帮助减少噪声并使得特征更加稳定。Hadamard积:用于在特征图中进行逐元素相乘(点乘),以加强语义信息和细节信息的融合。通道注意力(ChannelAttention):利用通道注意力机制来自动关注重要的特征通…...

flex布局 flex-end为什么overflow无法滚动及解决方法

flex-end为什么overflow无法滚动及解决方法 在使用Flexbox布局时&#xff0c;我们经常使用justify-content和align-items属性来定位子元素。其中&#xff0c;align-items属性用于控制子元素在交叉轴上的位置&#xff0c;例如顶部对齐、底部对齐或居中对齐等。当我们将align-it…...

为什么走资派还在走?

本文发表于《人民日报》1976年4月21日第2版,作者是桂志,有删减。毛主席指出:&ldquo;走资派还在走。&rdquo;认真学习毛主席的有关这个问题的一系列重要指示,正确认识社会主义时期这个阶级斗争现象,搞清楚为什么走资派还在走,对于我们坚持无产阶级专政下的继续革命…...

干字当头 破浪前进——2025年中国经济开局述评

走过很不平凡的2024年,我们迎来充满期待的2025年:&ldquo;十四五&rdquo;规划收官,新的五年规划呼之欲出,进一步全面深化改革纵深向前。&ldquo;坚持干字当头,增强信心、迎难而上、奋发有为,确保党中央各项决策部署落到实处。&rdquo;2024年12月召开的中央经…...

小红书登顶87国App Store 实时翻译功能在开发了

1月15日,第三方数据平台七麦数据显示,截至发稿,小红书在87个国家登上App Store的免费排行榜第一,包括美国、加拿大、澳大利亚、英国、意大利等国家。此外,它还在39个国家的App Store免费排行榜上位列第2至第10位。一位小红书员工告诉经济观察网,社区技术部门的其中一个组…...

拜登呼吁修改总统豁免权

美国《国会山报》报道,当地时间1月15日20时,美国总统拜登在白宫椭圆形办公室发表总统任内的告别演讲。拜登表示,美国应该&ldquo;修改宪法,明确任何总统都不能免于他或她在任期间犯下的罪行&rdquo;。&ldquo;总统的权力不是无限的,不是绝对的,也不应该是绝对的…...

说说小红书上和美国人交流的体验

美国的Tik Tok难民涌入小红书算是一个谁都没想到的黑天鹅事件。事实证明全球网民都是玩抽象整活的主,而TT难民涌入小红书本质也是一种赛博抽象。西大赛博难民选择小红书的原因据说是小红书只需要手机号(包括国外手机号)就能注册,不需要进行实名认证等,对西大难民来说是门槛…...

小红书两天涌入多少海外TikTok用户? 知情人士透露细节

小红书凤凰网科技讯 北京时间1月15日,据路透社报道,由于TikTok在美国面临即将被封禁的风险,许多所谓的&ldquo;TikTok难民&rdquo;涌入了小红书。据一位接近小红书的知情人士透露,仅两天时间内就有超过70万名新用户加入了小红书。根据应用数据研究公司Sensor Tower的…...