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

网站上面的logo怎么做wordpress图片宽度

网站上面的logo怎么做,wordpress图片宽度,人武部正规化建设经验,wordpress文本小工具栏概述 猫耳FM是中国最大的 95 后声音内容分享平台#xff0c;是B站重要平台之一#xff0c;深度合作国内顶级声优工作室#xff0c;打造了数百部精品广播剧#xff0c;全站播放总量超过百亿次。 MEPlayer 是猫耳 Android 技术团队研发的一款适用于音视频、直播、特效播放等…概述 猫耳FM是中国最大的 95 后声音内容分享平台是B站重要平台之一深度合作国内顶级声优工作室打造了数百部精品广播剧全站播放总量超过百亿次。 MEPlayer 是猫耳 Android 技术团队研发的一款适用于音视频、直播、特效播放等多种场景的跨进程播放框架。目前支持 音视频、直播、特效播放。支持自定义播放内核目前内置了 exo、bbp多媒体部门开发的轻量级播放内核都添加了边下边播支持可以自行扩展支持 ijk 等内核实现固定的几个接口即可。与业务完全解耦已在公司内多个团队使用。跨进程播放音视频、直播、特效播放进程被杀后自动恢复。自动管理音频焦点支持忽略焦点抢占与其他音视频应用同时播放。支持显示在通知栏和播控中心已适配包括鸿蒙猫耳FM 已通过华为测试配置在鸿蒙系统源码白名单里在内的国内系统。后台播放优化bbp 后台播视频支持暂停视频解码播放时后台保持网络连接能同时提升主进程和播放进程优先级保证应用播放时存活更久。支持切换清晰度、播放中途音视频互切、起播出错或者播放中途出错自动重试。基础功能播放列表、循环模式、进度跳转、快进、快退、倍速播放、设置音量、跳过片头片尾、定时暂停、播放完整首暂停等。 具体使用场景可以参考猫耳FM APP 音视频主播放场景 音视频播放页 直播、特效 直播间 短视频场景 首页推荐 - 小梦乡 列表播放以及过渡到播放页场景 首页推荐 - 播放大卡 配音秀 发现 - 活动 - 配音活动 单个音视频、特效播放场景 个人主页头像音、首页点击盲盒剧场、活动 - 运势语音、首页声音恋人 tab 下的推荐 UP 主播放、我的 - 启动音等。 起源 旧版本猫耳FM APP 内的大量的音视频播放场景使用了 ijk、ExoPlayer、MediaPlayer 等多种播放器方案且播放逻辑和业务逻辑高度耦合当播放场景出现新的需求改动成本巨大且编写需求代码的过程中易产生 bug原播放场景相关的代码缺少模块化代码复用程度低进而影响后期维护。因此项目迫切需要一套统一的播放框架以满足不同场景的需要。调研了主流的播放框架之后发现很难同时满足我们的多样化场景。在调研了主流的播放框架后发现没有现成方案能够满足项目的多样化场景于是我们开发了 MEPlayer0 重复逻辑、0 业务耦合API 友好开发的理解和接入成本都极小。 播放器流程 下图是一个简单的播放流程图。 MEPlayer、MEDirectPlayer 是音视频和直播业务直接接触的两个播放器入口MEPlayer 支持跨进程播放MEDirectPlayer 则直接在主进程播放这两个 Player 的基础 API 和播放逻辑代码都是共享的差异部分在于播放器入口实例和内核封装 Player 的连接相比于 MEPlayerMEDirectPlayer 缺少连接播控中心的能力。 为什么需要 MEDirectPlayer 呢因为对于闪屏、启动音等在启动 APP 一两秒内就要播放的场景跨进程播放是来不及的可能会出现需要播的时候进程还没连接好的状况。而跨进程部分逻辑是比较复杂的所以还是分离一个播放器入口对于后期维护和业务理解都更友好。 对于视频和特效播放需要绑定视频/特效容器的 SurfaceSurfaceListener 是在播放器内部管理的业务只需要传递容器 View 给播放框架即可目前支持 TextureView 和 SurfaceView业务如果设置过 SurfaceListener框架里也会兼容在对应方法回调时会给老的 listener 同时回调在列表场景视频卡片切换时会把业务设置的 listener 还给上一个卡片。特效播放比较特殊播放器入口是 AlphaVideoPlayer用到的播放内核 API 也不一样在跨进程 AIDL 调用中都是独立的方法但是业务调用的 API 跟音视频播放是一致的。 播放框架的状态机见下图 起播处理流程采用的拦截器模式对于全局的 https、免流处理等操作可以自定义一个拦截器注入到播放器中对于列表播放中某一条 item 没有 url 信息时也可以在默认的拦截器回调中请求接口返回一个新的 url 来播放。 interface PlayerPreProcessor {val name: String/*** Processor id业务自定义的 id 从 100 开始定前 100 是给框架预留的*/val id: Int/*** 处理器调用优先级值越大优先级越大最大为 100。设置的时候注意查看现有的其他处理器的优先级尽量不要重复*/get:IntRange(from 0L, to 100L)val priority: Int/*** param url 原始 url* param playItem 播放列表中的当前 item如果没有列表则为空* param playParam 播放参数* param scope 协程作用域* return 输出的结果*/suspend fun process(url: String?, playItem: PlayItem?, playParam: PlayParam?, scope: CoroutineScope): PlayerPreProcessResult }播放器回调统一采用 kotlin dsl 的形式简单示例如下 private val mPlayer MEPlayer(this).apply {onReady {// 打开 url 资源成功回调}onDuration {// 更新时长}onPlayingStateChanged { isPlaying, from -// 更新播放状态}onPositionUpdate {// 更新播放进度}onCompletion { // 播放结束}onRetry {// 播放出错会自动调用 onRetry 进行重试如果业务没有实现则跳转到 onError// onRetry 是一个 suspend 方法可以进行耗时操作需要返回一个 url可以是 player.originUrl也可以是请求后端返回的一个新 url}onError {// 错误处理} }MEPlayer 支持传入 LifecycleOwner可以在 LifecycleOwner onDestroy 的时候自动释放。构造方法为 /*** 播放器构造方法大多数场景都应该使用 MEPlayer会跨进程播放** param lifecycleOwner LifecycleOwner 对象对于可以在退出页面后继续播放的场景可以传 ProcessLifecycleOwner.get()其他场景可以传页面的 LifecycleOwner* param from 用于在日志 tag 上显示业务来源可以传页面的 TAG默认使用 lifecycleOwner 所在页面的 className* param type 播放器类型默认值为 PLAYER_TYPE_AUTO* PLAYER_TYPE_AUTO - 根据磁盘缓存键值对里 “player_type” 对应的值来选择播放器如果是 “exo” 则使用 ExoPlayer* 如果是 “bbp” 则使用 BBP 播放器默认使用 ExoPlayer。* PLAYER_TYPE_BB_PLAYER - 使用 BBP 播放器* PLAYER_TYPE_EXO_PLAYER - 使用 ExoPlayer* param scope 协程作用域用于播放器对象里创建协程管理协程生命周期默认值为 lifecycleOwner.lifecycleScope*/ class MEPlayer JvmOverloads constructor(lifecycleOwner: LifecycleOwner,from: String lifecycleOwner.tagName(),PlayerType type: String PLAYER_TYPE_AUTO,scope: CoroutineScope lifecycleOwner.lifecycleScope )播放框架还支持多实例场景配音秀和小梦乡场景都是无声视频配合音频一起播放的所以跨进程播放的时候要支持多个实例同时播放。先看下播放器的一段日志 // 音频 // 播放进程 I/ServicePlayer.Hypnosis.bbp.core1 onReady I/ServicePlayer.Hypnosis.bbp.core1 onPlaying, needRequestFocus: true I/ServicePlayer.Hypnosis.bbp.core1 updatePlaybackState, shouldShowInMediaSession: true, enableNotification: true, enableRating: false, enableLyric: false // 主进程 I/MEPlayer.Hypnosis.bbp.core1 onReady I/MEPlayer.Hypnosis.bbp.core1 updatePlayingState, isPlaying: true, reason: 1 (open), position: 12 (00:00), notifyCallback: true, notifyNotification: true // 视频 // 播放进程 I/ServicePlayer.HypnosisHomeFragment.bbp.core2 onReady I/ServicePlayer.HypnosisHomeFragment.bbp.core2 onPlaying, needRequestFocus: false I/ServicePlayer.HypnosisHomeFragment.bbp.core2 updatePlaybackState, shouldShowInMediaSession: false, enableNotification: false, enableRating: false, enableLyric: false // 主进程 I/MEPlayer.HypnosisHomeFragment.bbp.core2 onReady I/MEPlayer.HypnosisHomeFragment.bbp.core2 updatePlayingState, isPlaying: true, reason: 1 (open), position: 21 (00:00), notifyCallback: true, 可以看出播放器日志采用了多级 TAG 结构在播放框架的主流程的每一个类中打印的日志都能直接看出当前打印日志时所在的类、业务、播放内核类型和内核实例索引。播放器实例采用 SparseArrayCompat 来存储主进程和播放进程保证实例索引的一一对应关系。 在列表视频播放过渡到播放页场景中需要做到实例无缝过渡框架里会把播放页实例的参数传递给列表的实例然后释放原实例整个过程播放是持续进行的。 播放器优化 在网络连接上ExoPlayer 官方已经支持了 Cronet经过和多媒体部门、主站一起合作bbp 也添加了 Cronet 支持Cronet 是一个由 Google 开发的网络库 也是 Chrome 的网络栈它提供了高性能和可靠的网络访问能力支持 HTTP、HTTP/2 以及 HTTP/3 协议在 HTTP/3 下90% 的用户起播速度提升了 100ms 以上。 另外 ExoPlayer 的缓存支持其实并不友好音频 APP 的一个必备功能就是在播放的时候会持续缓存完整个音频同时进度条会更新缓存进度但是要想用 ExoPlayer 直接实现这点很难业内一般是用 AndroidVideoCache 来实现的并不优雅这里我修改了部分 ExoPlayer 的源码添加了支持内容较长不好展开讲。 音频焦点管理 音频焦点在框架内自动申请和释放业务只需要在初始化播放器时设置音频焦点类型和是否忽略焦点抢占即和其他应用同时播放即可。 player.run {audioFocusGain AUDIO_FOCUS_GAIN_TRANSIENTignoreFocusLoss true }在每个播放器实例中都会有焦点监听和处理 后台播放优化 在应用退到后台后如果进程包括主进程不是前台进程很可能会在几秒内被系统杀死。那么就需要在播放的时候通过调用 startForeground(int id, Notification notification) 将播放进程设置为前台进程前台进程需要绑定一个通知退到后台后可以发现播放进程的存活率明显提升但是播一会儿你会发现主进程没了。就是说主进程和播放进程都需要设置为前台进程但是产品需求上我们只有一个播放器通知所以主进程要用和播放进程一样的通知内容开启前台进程以保证用户切换音频的时候不会看到闪出一个非播放通知。这里我们主进程也开了个通知服务来更新通知播放进程只需要开启前台进程的时候绑定通知就好了后续通知的更新交由主进程完成。播放时退后台打印优先级可以看到两个进程都是较高的优先级。 adb shell $ cat /proc/pidof cn.missevan/oom_adj 3 $ cat /proc/pidof cn.missevan:player/oom_adj 3还有一种情况是主进程活着但是播放进程被杀死了或者播放进程出现问题崩溃了这时候主进程需要恢复播放进程不仅仅是启动进程也需要维持原有的进度恢复播放还需要创建新的通知开启前台进程。这些步骤都需要拿到原有的数据在播放进程存放这些数据不靠谱所以主进程执行的步骤都需要保存数据以供播放进程重连后使用。 播放失败重试包含中途网络断开媒体数据却没有缓存完、链接失效、seek 失败、切换清晰度失败、音视频切换失败等场景这些场景的重试逻辑是有所区分的要保证代码逻辑清晰符合需求又没有重复代码是比较困难的好在梳理异同点后把逻辑都聚合到了一块对于后期扩展也比较友好。这里通过 playType 区分场景核心逻辑如下 val playParamApplier: PlayParam.() - Unit {// 重试的时候复用上次的参数from(currentPlayParam)// 重试都是保持原来设置的 playWhenReady即使原始请求是不要 keepPlayingState 的重试也可以设为 true因为原始请求已经生效了重试就可以保持了keepPlayingState trueisSwitchUrl truestopPrevious falseisRetry true// 针对有的错误转换播放类型when (errorCode) {PLAYER_ERROR_CODE_OPEN_FAILED - {// 打开失败的情况直接按原来的参数重新打开即可isSwitchUrl 要传 false否则会没有 onReady、onDuration 回调isSwitchUrl falseposition thisBaseMediaPlayer.position}PLAYER_ERROR_CODE_SEEK_FAILED - {playType PLAYER_PLAY_TYPE_SEEK_RETRY}PLAYER_ERROR_CODE_SWITCH_QUALITY_FAILED - {// bbp 切换清晰度第一次出错以后会走到这里执行重试重试需要换播放类型playType PLAYER_PLAY_TYPE_SWITCH_QUALITY_RETRY}} }进入后台和离开视频页后暂停视频解码需要设置对应视频容器所在页面的 LifecycleOwner调用 videoPageLifecycleOwner thisXXXFragment 即可如果没有设置则会使用构造方法里的 LifecycleOwner。在后台播放时使用 WifiLockManager 和 WakeLockManager 启用 Wi-Fi 锁和唤醒锁可以让应用在后台也能持续联网保证播放的流畅性。 在国产的 ROM 里要想在后台持续播放保证应用运行的相关权限给够了才是最稳妥的所以我们还加了个后台播放优化设置页这个页面框架里不提供需要业务自行实现。 通知栏和播控中心 对于通知栏业务上既有使用系统媒体通知样式的需求也有使用自定义布局的需求这些不同样式的通知基本只有 UI 展示、按钮点击处理上的区别其他通知逻辑是基本一致的猫耳播放框架做到了业务只需要设置差异部分其他 API 调用保持一致。通知基础数据设置如下: // 音视频通知栏 player.updateNotificationData {smallIcon R.drawable.ic_player_notificationactionList arrayListOf(PLAYER_NOTIFICATION_ACTION_PLAY,PLAYER_NOTIFICATION_ACTION_PAUSE,PLAYER_NOTIFICATION_ACTION_PREVIOUS,PLAYER_NOTIFICATION_ACTION_NEXT,PLAYER_NOTIFICATION_ACTION_FAST_FORWARD,PLAYER_NOTIFICATION_ACTION_REWIND)showActionsInCompactView arrayListOf(1, 2, 3)contentAction AppConstants.PLAY_ACTIONcontentClassName MainActivity::class.java.namebizType PLAYER_FROM_MAINgroupId NotificationChannels.Play.groupIdchannelId NotificationChannels.Play.channelIdchannelName NotificationChannels.Play.channelNamechannelDesc NotificationChannels.Play.channelDescriptionvisibility NotificationCompat.VISIBILITY_PUBLIC } // 直播通知栏 updateNotificationData {smallIcon R.drawable.ic_notification_smallforceOngoing truecustomLayout R.layout.layout_notification_live_meplayercoverRadius 4defaultCover R.drawable.notification_live_default_avatarcontentAction AppConstants.PLAY_ACTIONcontentClassName MainActivity::class.java.namebizType PLAYER_FROM_LIVEgroupId NotificationChannels.Live.groupIdchannelId NotificationChannels.Live.channelIdchannelName NotificationChannels.Live.channelNamechannelDesc NotificationChannels.Live.channelDescriptionvisibility NotificationCompat.VISIBILITY_PUBLIC }对于播控的适配主要是要考虑 MIUI、ColorOS 等国产 ROM 和鸿蒙的差异除鸿蒙之外基本按官方文档更新 MediaSession 即可对于鸿蒙则要多一些适配比如鸿蒙支持下图两种场景 这里面歌词、收藏、快进快退等逻辑都是需要根据不同的业务设置来处理的目前业务只需要调用播放器对应的字段进行设置即可使用比较简单。 总结 本文介绍了猫耳FM在 Android 平台上开发媒体播放框架的实践经验包括架构设计、核心技术、优化改进等方面。希望通过这篇文章能够给广大的 Android 开发者提供一些有用的参考和启发也欢迎大家提出宝贵的意见和建议。 Android 学习笔录 Android 性能优化篇https://qr18.cn/FVlo89 Android Framework底层原理篇https://qr18.cn/AQpN4J Android 车载篇https://qr18.cn/F05ZCM Android 逆向安全学习笔记https://qr18.cn/CQ5TcL Android 音视频篇https://qr18.cn/Ei3VPD Jetpack全家桶篇内含Composehttps://qr18.cn/A0gajp OkHttp 源码解析笔记https://qr18.cn/Cw0pBD Kotlin 篇https://qr18.cn/CdjtAF Gradle 篇https://qr18.cn/DzrmMB Flutter 篇https://qr18.cn/DIvKma Android 八大知识体https://qr18.cn/CyxarU Android 核心笔记https://qr21.cn/CaZQLo Android 往年面试题锦https://qr18.cn/CKV8OZ 2023年最新Android 面试题集https://qr18.cn/CgxrRy Android 车载开发岗位面试习题https://qr18.cn/FTlyCJ 音视频面试题锦https://qr18.cn/AcV6Ap
http://www.w-s-a.com/news/913991/

相关文章:

  • 佘山做网站谷歌云做网站
  • 免费发布信息网站大全666做p2p网站费用
  • 北京 网站建设咨询顾问公司网络公司有几家
  • 设计类网站如何用ps做网站首页
  • 品牌网站建设的关键事项设计网有哪些
  • 网站没收录徐州建设工程审图中心网站
  • 网站建设记账做什么科目erp系统有哪些软件
  • 泰拳图片做网站用哪里有做空包网站的
  • 查外链网站重庆做网站微信的公司
  • 有没有外包活的网站如何做网站快捷键的元素
  • 公司网站赏析网站制作2019趋势
  • 企业进行网站建设的方式有( )推广引流违法吗
  • 按营销型网站要求重做网站 费用点金网站建设
  • 深圳做网站互联网服务
  • 网站sem托管wordpress安装无法连接数据库
  • 深圳网站建设开发公司哪家好微信小程序商家入口
  • 江门站排名优化建立什么网站赚钱
  • 科普文章在那个网站做招聘网站代做
  • 监控设备东莞网站建设游戏网站域名
  • 对商家而言网站建设的好处网址导航怎么彻底删除
  • app设计网站模板企业展厅策划设计公司有哪些
  • wordpress销售主题手机网站关键词优化
  • 怎么查一个网站是什么程序做的三亚城乡建设局网站
  • 深圳分销网站设计公司做网站一般需要多久
  • 企业网站设计代码丹东seo排名公司
  • 企业网站建设定制开发服务网站建设说课ppt
  • 大连市城乡建设局网站网站免费网站入口
  • 做暧网站网站备案ps
  • 知名网站建设公司电话长子网站建设
  • 网站建设的意义与目的建立什么船籍港