制作一个OpenHarmony视频播放器

简介

媒体子系统是 OpenHarmony 中重要的子系统,可以提供音视频播放能力。媒体子系统为开发者提供一套简单且易于理解的接口,使得开发者能够方便接入系统并使用系统的媒体资源。媒体子系统提供以下常用功能:

  • 音视频播放(AVPlayer9+),AudioPlayer6+ 和 VideoPlayer8+ 整合,升级了状态机和错误码,推荐使用
  • 音视频录制(AVRecorder9+),AudioRecorder6+ 和 VideoRecorder9+ 整合,推荐使用
  • 音频播放(AudioPlayer6+),AVPlayer9+ 发布后停止维护,请使用 AVPlayer9+
  • 视频播放(VideoPlayer8+),AVPlayer9+ 发布后停止维护,请使用 AVPlayer9+
  • 音频录制(AudioRecorder6+),AVRecorder9+ 发布后停止维护,请使用 AVRecorder9+
  • 视频录制(VideoRecorder9+),AVRecorder9+ 发布后停止维护,请使用 AVRecorder9+

从 3.2 开始 OpenHarmony 推出了 AVPlayer 和 AVRecorder 接口,之前的 VideoPlayer、AudioPlayer 这些接口会停止维护,所以我们今天学习下怎么使用 AVPlayer 接口


导入模块

import media from '@ohos.multimedia.media';` ​
  • 创建 avplayer
this.avPlayer = await media.createAVPlayer()` ​

如上,我们使用的是 promise 接口,对应的接口定义为:

/**
  * Creates an AVPlayer instance.
  * @since 9
  * @syscap SystemCapability.Multimedia.Media.AVPlayer
  * @param callback Callback used to return AVPlayer instance if the operation is successful; returns null otherwise.
  * @throws { BusinessError } 5400101 - No memory. Return by callback.
  */
  function createAVPlayer(callback: AsyncCallback<AVPlayer>): void;

 /**
  * Creates an AVPlayer instance.
  * @since 9
  * @syscap SystemCapability.Multimedia.Media.AVPlayer
  * @returns A Promise instance used to return AVPlayer instance if the operation is successful; returns null otherwise.
  * @throws { BusinessError } 5400101 - No memory. Return by promise.
  */
  function createAVPlayer() : Promise<AVPlayer>;` ​

*   注册 avplayer 回调
   
   `//注册状态变化回调,不同状态时做不同动作
   avPlayer.on('stateChange', async (state, reason) => {
   	……
   })
   //注册时间变化回调,方便更新进度条时间
   avPlayer.on('timeUpdate', (time:number) => {
   	……
   })
  • avplayer 播放流程

//视频播放伪代码
async avPlayerDemo() {
    this.avPlayer.on('stateChange', async (state, reason) => {
        switch (state) {
            case 'idle': // 成功调用reset接口后触发该状态机上报
                console.info(TAG + 'state idle called')
                this.avPlayer.release() // 释放avplayer对象
                break;
            case 'initialized': // avplayer 设置播放源后触发该状态上报
                console.info(TAG + 'state initialized called ')
                this.avPlayer.surfaceId = this.surfaceID // 设置显示画面,当播放的资源为纯音频时无需设置
                this.avPlayer.prepare().then(() => {
                    console.info(TAG+ 'prepare success');
                }, (err) => {
                    console.error(TAG + 'prepare filed,error message is :' + err.message)
                })
                break;
            case 'prepared': // prepare调用成功后上报该状态机
                console.info(TAG + 'state prepared called')
                this.avPlayer.play() // 调用播放接口开始播放
                break;
            case 'playing': // play成功调用后触发该状态机上报
                console.info(TAG + 'state playing called')
                if (this.count == 0) {
                    this.avPlayer.pause() // 调用暂停播放接口
                } else {
                    this.avPlayer.seek(10000, media.SeekMode.SEEK_PREV_SYNC) // 前向seek置10秒处,触发seekDone回调函数
                }
                break;
            case 'paused': // pause成功调用后触发该状态机上报
                console.info(TAG + 'state paused called')
                if (this.count == 0) {
                    this.count++
                    this.avPlayer.play() // 继续调用播放接口开始播放
                }
                break;
            case 'completed': // 播放结束后触发该状态机上报
                console.info(TAG + 'state completed called')
                this.avPlayer.stop() //调用播放结束接口
                break;
            case 'stopped': // stop接口成功调用后触发该状态机上报
                console.info(TAG + 'state stopped called')
                this.avPlayer.reset() // 调用reset接口初始化avplayer状态
                break;
            case 'released':
                console.info(TAG + 'state released called')
                break;
            case 'error':
                console.info(TAG + 'state error called')
                break;
            default:
                console.info(TAG + 'unkown state :' + state)
                break;
        }
    })

    // 创建avPlayer实例对象
    this.avPlayer = await media.createAVPlayer()
    let fdPath = 'fd://'
    let pathDir = "/data/storage/el2/base/haps/entry/files" // pathDir在FA模型和Stage模型的获取方式不同,请参考开发步骤首行的说明,根据实际情况自行获取。
    // path路径的码流可通过"hdc file send D:\xxx\H264_AAC.mp4 /data/app/el2/100/base/ohos.acts.multimedia.media.avplayer/haps/entry/files" 命令,将其推送到设备上
    let path = pathDir  + '/H264_AAC.mp4'
    let file = await fs.open(path)
    fdPath = fdPath + '' + file.fd
    //赋值url后就会进入stateChange callback
    this.avPlayer.url = fdPath
}
  • 其他播放控制接口
          /**
         * Prepare audio/video playback, it will request resource for playing.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param callback A callback instance used to return when prepare completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
         * @throws { BusinessError } 5400106 - Unsupport format. Return by callback.
         */
        prepare(callback: AsyncCallback<void>): void;
    
        /**
         * Prepare audio/video playback, it will request resource for playing.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @returns A Promise instance used to return when prepare completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
         * @throws { BusinessError } 5400106 - Unsupport format. Return by promise.
         */
        prepare(): Promise<void>;
    
        /**
         * Play audio/video playback.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param callback A callback instance used to return when play completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
         */
        play(callback: AsyncCallback<void>): void;
    
        /**
         * Play audio/video playback.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @returns A Promise instance used to return when play completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
         */
        play(): Promise<void>;
    
        /**
         * Pause audio/video playback.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param callback A callback instance used to return when pause completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
         */
        pause(callback: AsyncCallback<void>): void;
    
        /**
         * Pause audio/video playback.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @returns A Promise instance used to return when pause completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
         */
        pause(): Promise<void>;
    
        /**
         * Stop audio/video playback.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param callback A callback instance used to return when stop completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
         */
        stop(callback: AsyncCallback<void>): void;
    
         /**
          * Stop audio/video playback.
          * @since 9
          * @syscap SystemCapability.Multimedia.Media.AVPlayer
          * @returns A Promise instance used to return when stop completed.
          * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
          */
        stop(): Promise<void>;
    
        /**
         * Reset AVPlayer, it will to idle state and can set src again.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param callback A callback instance used to return when reset completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
         */
        reset(callback: AsyncCallback<void>): void;
    
        /**
         * Reset AVPlayer, it will to idle state and can set src again.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @returns A Promise instance used to return when reset completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
         */
        reset(): Promise<void>;
    
        /**
         * Releases resources used for AVPlayer.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param callback A callback instance used to return when release completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by callback.
         */
        release(callback: AsyncCallback<void>): void;
    
        /**
         * Releases resources used for AVPlayer.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @returns A Promise instance used to return when release completed.
         * @throws { BusinessError } 5400102 - Operation not allowed. Return by promise.
         */
        release(): Promise<void>;
    
        /**
         * Jumps to the specified playback position.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param timeMs Playback position to jump, should be in [0, duration].
         * @param mode See @SeekMode .
         */
        seek(timeMs: number, mode?:SeekMode): void;` ​
  • 其他回调接口
          /**
         * Register or unregister listens for media playback events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback stateChange event.
         */
        on(type: 'stateChange', callback: (state: AVPlayerState, reason: StateChangeReason) => void): void;
        off(type: 'stateChange'): void;
        /**
         * Register or unregister listens for media playback events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback volume event.
         */
        on(type: 'volumeChange', callback: Callback<number>): void;
        off(type: 'volumeChange'): void;
        /**
         * Register or unregister listens for media playback events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback end of stream
         */
        on(type: 'endOfStream', callback: Callback<void>): void;
        off(type: 'endOfStream'): void;
        /**
         * Register or unregister listens for media playback events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback seekDone event.
         */
        on(type: 'seekDone', callback: Callback<number>): void;
        off(type: 'seekDone'): void;
        /**
         * Register or unregister listens for media playback events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback speedDone event.
         */
        on(type: 'speedDone', callback: Callback<number>): void;
        off(type: 'speedDone'): void;
        /**
         * Register or unregister listens for media playback events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback setBitrateDone event.
         */
        on(type: 'bitrateDone', callback: Callback<number>): void;
        off(type: 'bitrateDone'): void;
        /**
         * LRegister or unregister listens for media playback events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback timeUpdate event.
         */
        on(type: 'timeUpdate', callback: Callback<number>): void;
        off(type: 'timeUpdate'): void;
        /**
         * Register or unregister listens for media playback events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback durationUpdate event.
         */
        on(type: 'durationUpdate', callback: Callback<number>): void;
        off(type: 'durationUpdate'): void;
        /**
         * Register or unregister listens for video playback buffering events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback buffering update event to listen for.
         * @param callback Callback used to listen for the buffering update event, return BufferingInfoType and the value.
         */
        on(type: 'bufferingUpdate', callback: (infoType: BufferingInfoType, value: number) => void): void;
        off(type: 'bufferingUpdate'): void;
        /**
         * Register or unregister listens for start render video frame events.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback event return .
         */
        on(type: 'startRenderFrame', callback: Callback<void>): void;
        off(type: 'startRenderFrame'): void;
        /**
         * Register or unregister listens for video size change event.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback event return video size.
         */
        on(type: 'videoSizeChange', callback: (width: number, height: number) => void): void;
        off(type: 'videoSizeChange'): void;
        /**
         * Register or unregister listens for audio interrupt event, refer to {@link #audio.InterruptEvent}
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback event return audio interrupt info.
         */
        on(type: 'audioInterrupt', callback: (info: audio.InterruptEvent) => void): void;
        off(type: 'audioInterrupt'): void;
        /**
         * Register or unregister listens for available bitrate list collect completed events for HLS protocol stream playback.
         * This event will be reported after the {@link #prepare} called.
         * @since 9
         * @syscap SystemCapability.Multimedia.Media.AVPlayer
         * @param type Type of the playback event to listen for.
         * @param callback Callback used to listen for the playback event return available bitrate list.
         */
        on(type: 'availableBitrates', callback: (bitrates: Array<number>) => void): void;
        off(type: 'availableBitrates'): void;

简单样例

  • 界面
 build() {
       Stack({ alignContent: Alignment.Center }) {
         if (this.isShowMenu) {
           Column() {
             //视频名称
             PlayTitle({ title: this.displayName, handleBack: this.handleBack })
             Row() {
               //播放控件
               PreVideo({ handleClick: this.handlePrevClick })
               PlayButton({ isPlaying: $isPlaying })
               NextVideo({ handleClick: this.handleNextClick })
             }
             .margin({ top: '40%' })
   
             Blank()
             //时间刻度
             Row() {
               Text(getTimeString(this.currentTime))
                 .fontSize(25)
                 .fontColor(Color.White)
               Blank()
               Text(this.fileAsset ? getTimeString(this.fileAsset.duration) : '00:00')
                 .fontSize(25)
                 .fontColor(Color.White)
             }
             .width('95%')
   		  //进度条
             Slider({ value: this.fileAsset ? this.currentTime / this.fileAsset.duration * 100 : 0 })
               .width('92%')
               .selectedColor(Color.White)
               .onChange((value: number) => {
                 Logger.info(TAG, 'seek time change')
                 this.currentTime = this.fileAsset.duration * value / 100
                 this.videoPlayer.seek(this.currentTime)
               })
           }
           .height('100%')
           .zIndex(2)
         }
         Row() {
           XComponent({
             id: 'componentId',
             type: 'surface',
             controller: this.mxcomponentController
           })
             .onLoad(() => {
               Logger.info(TAG, 'onLoad is called')
               this.playVideo()
             })
             .width('100%')
             .aspectRatio(this.ratio)
         }
         .height('100%')
         .width('100%')
         .justifyContent(FlexAlign.Center)
       }
       .width('100%')
       .height('100%')
       .backgroundColor(Color.Black)
       .onClick(() => {
         this.isShowMenu = !this.isShowMenu
       })
     }
  • 播放
      //根据视频文件获取视频源尺寸并生成surface
      //视频文件的路径在/storage/media/100/local/files/Videos
      async prepareVideo() {
        this.ratio = this.fileAsset.width / this.fileAsset.height
        this.mxcomponentController.setXComponentsurfaceSize({
          surfaceWidth: this.fileAsset.width,
          surfaceHeight: this.fileAsset.height
        })
        this.surfaceId = this.mxcomponentController.getXComponentsurfaceId()
        this.fd = await this.fileAsset.open('Rw')
        Logger.info(TAG, `fd://' ${this.fd} `)
        return 'fd://' + this.fd
      }
      //初始化视频文件并初始化avplayer
      async playVideo() {
        Logger.info(TAG, 'playVideo')
        try{
          await this.getMediaList()
          let fdPath = await this.prepareVideo()
          this.videoPlayer.on('timeUpdate', (time:number) => {
            console.info('timeUpdate success,and new time is :' + time)
            this.currentTime = time;
          })
          await this.videoPlayer.initVideoPlayer(fdPath, this.surfaceId)
          this.isPlaying = true
        }catch(error) {
          Logger.info(TAG, `playVideo error ${JSON.stringify(error)}`)
        }
      }

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

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

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

相关文章

TestNG执行测试用例的方法

TestNG是一个非常好用d自动化测试框架&#xff0c;对于经常使用selenium做web端UI测试的童鞋来说是个不错的工具。 具备基本常识的测试童鞋们&#xff0c;可能需要知道存在即合理&#xff0c;存在即有用的道理。任何一个工具&#xff0c;或者一件事的存在如果令人得不到益处&am…

前端大屏项目适配方法

要在F11全屏模式下查看 方法一&#xff0c;rem font-size 动态设置HTML根字体大小 和 body 字体大小&#xff08;lib_flexible.js&#xff09; 将设计稿的宽&#xff08;1920&#xff09;平均分成 24 等份&#xff0c; 每一份为 80px。HTML字体大小就设置为 80 px&#xff…

C/C++ 配置 jemalloc 的一些选项,处理一些疑似内存泄漏的问题。

在 jemalloc 之中有三种配置 jemalloc 选项的一些方式。 1、修改选项代码默认值&#xff08;重新编译&#xff09; 2、修改环境变量 MALLOC_CONF&#xff0c;并重启应用程序 注意&#xff1a; 仅支持 opt. 节配置选项 export MALLOC_CONF"retain:true,dirty_decay_ms:2…

什么是图神经网络?

什么是图神经网络&#xff1f; GNN 将深度学习的预测能力应用于丰富的数据结构&#xff0c;这些数据结构将对象及其关系描述为图中由线连接的点。 当两种技术融合时&#xff0c;它们可以创造出新奇而美妙的东西——比如手机和浏览器融合在一起打造智能手机。 如今&#xff0…

初学网络编程

网络编程是指编写能够在网络环境中运行&#xff0c;进行数据通信的程序的过程。它涵盖了从建立网络连接、发送和接收数据&#xff0c;到关闭连接等一系列操作。网络编程是开发网络应用程序的基础&#xff0c;它使得不同的计算机和设备能够通过网络进行数据交换和通信。 三个核…

《手把手教你》系列基础篇(八十三)-java+ selenium自动化测试-框架设计基础-TestNG测试报告-下篇(详解教程)

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 其实前边好像简单的提到过测试报告&#xff0c;宏哥觉得这部分比较重要&#xff0c;就着重讲解和介绍一下。报告是任何测试执行中最重要的部分&#xff0c;因为它可以帮助用户了…

Flask快速搭建文件上传服务与接口

说明&#xff1a;仅供学习使用&#xff0c;请勿用于非法用途&#xff0c;若有侵权&#xff0c;请联系博主删除 作者&#xff1a;zhu6201976 一、需求背景 前端通过浏览器&#xff0c;访问后端服务器地址&#xff0c;将目标文件进行上传。 访问地址&#xff1a;http://127.0.0…

Java 中文官方教程 2022 版(三)

原文&#xff1a;docs.oracle.com/javase/tutorial/reallybigindex.html 对象 原文&#xff1a;docs.oracle.com/javase/tutorial/java/javaOO/objects.html 一个典型的 Java 程序会创建许多对象&#xff0c;正如您所知&#xff0c;这些对象通过调用方法进行交互。通过这些对象…

前端开发攻略---简化响应式设计:利用 SCSS 优雅管理媒体查询

1、演示 2、未优化前的代码 .header {width: 100px;height: 100px;background-color: red; } media (min-width: 320px) and (max-width: 480px) {.header {width: 10px;} } media (min-width: 320px) and (max-width: 480px) {.header {height: 20px;} } media (min-width: 48…

详细介绍微信小程序app.js

这一节&#xff0c;我们详细介绍app.js 这个文件。这个文件的重要性我就不再赘述&#xff0c;前面已经介绍了。 一、app.js是项目的主控文件 任何一个程序都是需要一个入口的&#xff0c;就好比我们在学c的时候就会有一个main函数&#xff0c;其他语言基本都是一样。很明确的…

隆道商机订阅服务|“您有一条新的商机,请注意查收”

隆道商机订阅服务 自定义关键词&#xff0c;智能甄别商机&#xff0c;随时随地查看&#xff0c;多平台实时推送。 核心功能 商机无限查 您可以根据不同的维度&#xff0c;如项目类型、项目地区等&#xff0c;对招标采购信息进行查询和筛选&#xff0c;以精准查找全网范围内的…

【Spring源码】JDBC数据源访问实现

一、阅读线索 开始我们今天的对Spring的【模块阅读】&#xff0c;来看看Data Access的JDBC模块是怎么设计的。 源码阅读前&#xff0c;我们要先思考下本次的阅读线索&#xff1a; JDBC模块有什么作用该模块是怎么设计的我们从这个模块可以学到什么 二、探索 关于阅读线索一…

Python实现BOA蝴蝶优化算法优化Catboost回归模型(CatBoostRegressor算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 蝴蝶优化算法(butterfly optimization algorithm, BOA)是Arora 等人于2019年提出的一种元启发式智能算…

十分钟到底能不能讲明白ROS到底能做啥

总结 录完视频发现十分钟不能&#xff0c;总共花了20分钟。 提纲&#xff1a; 课程、竞赛、论文Linux、C、Python、Github和ROS关联性强平台-资格和ROS关联性弱速度-成绩路径规划-全局和局部全局-侧重路径长短-找一条最优&#xff08;短&#xff09;的路局部-侧重速度控制-用…

数据可视化-ECharts Html项目实战(10)

在之前的文章中&#xff0c;我们学习了如何在ECharts中编写雷达图&#xff0c;实现特殊效果的插入运用&#xff0c;函数的插入&#xff0c;以及多图表雷达图。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&…

Python基于Django的微博热搜、微博舆论可视化系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

host文件nginx代理 综合理解

之前一直理解得很糙 导致遇到问题很迷糊 今天经过大佬两句话讲明白了 特此记录 host文件 首先host做了代理 也就是对浏览器的DNS寻址做了拦截 具体原理可以参照当我们在地址栏输入URL的时候浏览器发生了什么 例如127.0.0.1 www.baidu.com 将 127.0.0.1 www.baidu.com 链接自…

春游江淮|出发,上宁国“村游”去

竹川村、赤岸村打卡佳处&#xff0c;春花烂漫,春意盎然,胡乐镇竹川村、赤岸村的油菜花,是宁国春天不可错过的风光。等大片大片的油菜花盛放,与悠悠远山交相辉映,可以来此骑行、散步,静静欣赏美好的春日风光。 山门村 世外桃源经过奇特的“山门洞”,来到山门村,村内古木参天,在春…

Cloudshark数据包分析功能介绍

什么是CloudShark CloudShark是一种基于Web的数据包分析平台&#xff0c;可以认为是wiresshark的cloud版本&#xff0c;但是其在威胁分析等方面比Wireshark的功能强大&#xff0c;如下是他们的主要区别。 Wireshark VS Cloudshark Wireshark定位是一款本地开源的网络数据包分…

2024年第十四届MathorCup数学应用挑战赛B题解题思路

B题https://mbd.pub/o/bread/ZZ6Wm5dx 问题1:对于附件I(Pre_test文件夹)给定的三张甲骨文原始拓片图 片进行图像预处理&#xff0c;提取图像特征&#xff0c;建立甲骨文图像预处理模型&#xff0c;实现对 甲骨文图像干扰元素的初步判别和处理。 针对问题1&#xff0c;对于附件…