猫耳 Android 播放框架开发实践

概述

猫耳FM是中国最大的 95 后声音内容分享平台,是B站重要平台之一,深度合作国内顶级声优工作室,打造了数百部精品广播剧,全站播放总量超过百亿次。

MEPlayer 是猫耳 Android 技术团队研发的一款适用于音视频、直播、特效播放等多种场景的跨进程播放框架。目前支持:

  • 音视频、直播、特效播放。
  • 支持自定义播放内核,目前内置了 exo、bbp(多媒体部门开发的轻量级播放内核),都添加了边下边播支持,可以自行扩展支持 ijk 等内核,实现固定的几个接口即可。
  • 与业务完全解耦,已在公司内多个团队使用。
  • 跨进程播放音视频、直播、特效,播放进程被杀后自动恢复。
  • 自动管理音频焦点,支持忽略焦点抢占(与其他音视频应用同时播放)。
  • 支持显示在通知栏和播控中心,已适配包括鸿蒙(猫耳FM 已通过华为测试,配置在鸿蒙系统源码白名单里)在内的国内系统。
  • 后台播放优化:bbp 后台播视频支持暂停视频解码;播放时后台保持网络连接;能同时提升主进程和播放进程优先级保证应用播放时存活更久。
  • 支持切换清晰度、播放中途音视频互切、起播出错或者播放中途出错自动重试。
  • 基础功能:播放列表、循环模式、进度跳转、快进、快退、倍速播放、设置音量、跳过片头片尾、定时暂停、播放完整首暂停等。

具体使用场景可以参考猫耳FM APP:

音视频主播放场景: 音视频播放页;

直播、特效: 直播间;

短视频场景: 首页推荐 -> 小梦乡;

列表播放以及过渡到播放页场景: 首页推荐 -> 播放大卡;

配音秀: 发现 -> 活动 -> 配音活动;

单个音视频、特效播放场景: 个人主页头像音、首页点击盲盒剧场、活动 -> 运势语音、首页声音恋人 tab 下的推荐 UP 主播放、我的 -> 启动音等。

起源

旧版本猫耳FM APP 内的大量的音视频播放场景,使用了 ijk、ExoPlayer、MediaPlayer 等多种播放器方案,且播放逻辑和业务逻辑高度耦合,当播放场景出现新的需求,改动成本巨大,且编写需求代码的过程中易产生 bug;原播放场景相关的代码缺少模块化,代码复用程度低,进而影响后期维护。因此,项目迫切需要一套统一的播放框架,以满足不同场景的需要。调研了主流的播放框架之后,发现很难同时满足我们的多样化场景。在调研了主流的播放框架后,发现没有现成方案能够满足项目的多样化场景,于是我们开发了 MEPlayer,0 重复逻辑、0 业务耦合,API 友好,开发的理解和接入成本都极小。

播放器流程

下图是一个简单的播放流程图。

MEPlayer、MEDirectPlayer 是音视频和直播业务直接接触的两个播放器入口,MEPlayer 支持跨进程播放,MEDirectPlayer 则直接在主进程播放,这两个 Player 的基础 API 和播放逻辑代码都是共享的,差异部分在于播放器入口实例和内核封装 Player 的连接,相比于 MEPlayer,MEDirectPlayer 缺少连接播控中心的能力。

为什么需要 MEDirectPlayer 呢?因为对于闪屏、启动音等在启动 APP 一两秒内就要播放的场景,跨进程播放是来不及的,可能会出现需要播的时候进程还没连接好的状况。而跨进程部分逻辑是比较复杂的,所以还是分离一个播放器入口对于后期维护和业务理解都更友好。

对于视频和特效播放,需要绑定视频/特效容器的 Surface,SurfaceListener 是在播放器内部管理的,业务只需要传递容器 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_TRANSIENT
	ignoreFocusLoss = 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 = true
    isSwitchUrl = true
    stopPrevious = false
    isRetry = true
    // 针对有的错误,转换播放类型
    when (errorCode) {
        PLAYER_ERROR_CODE_OPEN_FAILED -> {
            // 打开失败的情况直接按原来的参数重新打开即可,isSwitchUrl 要传 false,否则会没有 onReady、onDuration 回调
            isSwitchUrl = false
            position = this@BaseMediaPlayer.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 = this@XXXFragment 即可,如果没有设置则会使用构造方法里的 LifecycleOwner。在后台播放时使用 WifiLockManagerWakeLockManager 启用 Wi-Fi 锁和唤醒锁可以让应用在后台也能持续联网,保证播放的流畅性。

在国产的 ROM 里,要想在后台持续播放,保证应用运行的相关权限给够了才是最稳妥的,所以我们还加了个后台播放优化设置页,这个页面框架里不提供,需要业务自行实现。

通知栏和播控中心

对于通知栏,业务上既有使用系统媒体通知样式的需求,也有使用自定义布局的需求,这些不同样式的通知,基本只有 UI 展示、按钮点击处理上的区别,其他通知逻辑是基本一致的,猫耳播放框架做到了业务只需要设置差异部分,其他 API 调用保持一致。通知基础数据设置如下:

// 音视频通知栏
player.updateNotificationData {
    smallIcon = R.drawable.ic_player_notification
    actionList = 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_ACTION
    contentClassName = MainActivity::class.java.name
    bizType = PLAYER_FROM_MAIN
    groupId = NotificationChannels.Play.groupId
    channelId = NotificationChannels.Play.channelId
    channelName = NotificationChannels.Play.channelName
    channelDesc = NotificationChannels.Play.channelDescription
    visibility = NotificationCompat.VISIBILITY_PUBLIC
}
// 直播通知栏
updateNotificationData {
    smallIcon = R.drawable.ic_notification_small
    forceOngoing = true
    customLayout = R.layout.layout_notification_live_meplayer
    coverRadius = 4
    defaultCover = R.drawable.notification_live_default_avatar
    contentAction = AppConstants.PLAY_ACTION
    contentClassName = MainActivity::class.java.name
    bizType = PLAYER_FROM_LIVE
    groupId = NotificationChannels.Live.groupId
    channelId = NotificationChannels.Live.channelId
    channelName = NotificationChannels.Live.channelName
    channelDesc = NotificationChannels.Live.channelDescription
    visibility = 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全家桶篇(内含Compose):https://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

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

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

相关文章

处理大数据的基础架构,OLTP和OLAP的区别,数据库与Hadoop、Spark、Hive和Flink大数据技术

处理大数据的基础架构,OLTP和OLAP的区别,数据库与Hadoop、Spark、Hive和Flink大数据技术 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学生都得去找开发,测开 测开的话&am…

数据链路层中存在的报文ip,arp,rarp

IP数据报 ARP请求/应答报 RARP请求/应答报 IP数据报 这里的目的地址和源地址是MAC地址。 这个被称为 MAC 地址,是一个网卡的物理地址,用十六进制,6 个 byte 表示。 MAC 地址是一个很容易让人误解的地址。因为 MAC 地址号称全球唯一&…

如何选择合适的千兆或万兆光模块

随着数字化转型的加快和云计算、物联网等技术的迅猛发展,对高带宽和高速度通信的需求将持续增长。光模块作为实现高速光纤通信的关键组件,在数据中心、通信网络、云服务等领域得到更广泛的应用。对于用户来说,如何选择适合自己应用的光模块是…

Vue elemen ui 移除上次校验与部分清除上次校验

场景: 可以切换类型,下面的输入框参数也会随着改变。 如果不清除上次的校验就会出现,之前的大陆企业的校验还会出现在香港企业的校验中 方法: watch:{ruleForm.paymentSubjectType:{ 通过监听表单的类型来调用 clearValidate方…

LV.12 D13 UART实验 学习笔记

一、UART帧格式详解 UART Universal Asynchronous Receiver Transmitter 即 通用异步收发器,是一种通用的串行、异步通信总线 该总线有两条数据线,可以实现全双工的发送和接收,在嵌入式系统中常用于主机与辅助设备之间的通信。 通…

API文档自动生成

API文档自动生成 背景smart-doc配置效果图 背景 对于API接口文档自动生成,可能大家,最新想到的是用swagger,但是有以下问题: 对代码侵入太强版本升级,并不兼容不能生成各种类型的文档 所以,今天给大家推荐…

Python Django 之模板继承详解(extends)

文章目录 1 概述1.1 目的1.2 标签:block、extends1.3 目录结构 2 templates 目录2.1 base.html:父页面2.2 login.html:子页面 3 其它代码3.1 settings.py3.2 views.py3.3 urls.py 1 概述 1.1 目的 模板继承 和 类继承 的目的是一样的&#…

【已解决】PPT不能转换成PDF文档怎么办?

PPT可以转换成PDF文档,只需要点击PPT菜单页面中的【文件】选项,再点击【导出】即可转换,如果转换时发现【导出】选项不可选,无法完成转换怎么办?以下3种方法可以试试! 出现上面这种情况,我们可以…

HWebkit库的程序示例

HWebkit库的爬虫程序,并且能够使用指定的服务器。以下是代码的每一行的中文解释: import HWebkit import Network.HTTP.Client import Network.HTTP.Client.TLS import Data.Text.Encoding ​ -- 创建服务器的连接,使用的端口和主机是 proxy…

计算机服务器中了mallad勒索病毒怎么办,勒索病毒解密恢复

警惕,警惕,企业主多警惕,新型网络勒索病毒出来了,近期,云天数据恢复中心,接到了某企业的求助,企业的计算机服务器中了mallad后缀勒索病毒,导致企业计算机系统瘫痪,无法正…

Vue3.0 reactive与ref :VCA模式

简介 Vue3 最大的一个变动应该就是推出了 CompositionAPI,可以说它受ReactHook 启发而来;它我们编写逻辑更灵活,便于提取公共逻辑,代码的复用率得到了提高,也不用再使用 mixin 担心命名冲突的问题。 ref 与 reactive…

yolov7模型轻量化改进之MobileOne骨干替换

本文在之前文章yolov7分割训练的基础上进行改进: https://blog.csdn.net/qq_41920323/article/details/129464115?spm=1001.2014.3001.5502 具体GitHub工程下载,环境安装配置,数据准备等,请借鉴之前的文章,此处只介绍如何进行改进。 MobileOne地址:https://github.com…

通付盾Web3专题 | 智能账户:数字时代基础单元

2008年10月31日,中本聪(Satoshi Nakamoto)在P2P foundation 网站发布比特币白皮书《比特币:一种点对点的电子现金系统》。转眼距比特币白皮书发布已过去15年。2009年1月比特币网络正式推出,当时每个比特币的价格仅为0.…

设置防火墙

1.RHEL7中的防火墙类型 防火墙只能同时使用一张,firewall底层调用的还是lptables的服务: firewalld:默认 ,基于不同的区域做规则 iptables: RHEL6使用,基于链表 Ip6tables Ebtables 2.防火墙的配置方式 查看防火墙状态: rootlinuxidc -]#systemct…

idea集成测试插件替代postman

idea集成测试插件替代postman 兄弟萌,你再测试接口是否无bug是否流畅的时候是否还在使用“postman”来回切换进行测试呢? 页面切换进行测试,有没有感觉很麻烦呢? 打开postman,输入接口地址,有没有感觉很麻烦…

拓扑排序专题1 拓扑排序

题目: 样例: 输入 4 5 0 1 0 2 0 3 1 2 3 2 输出 0 1 3 2 思路: 拓扑序列含义 一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y)(x,y), x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列…

阿里云无影升级2.0 云电脑解决方案时代到来

10月31日,杭州云栖大会上,阿里云宣布无影全新升级2.0:从云电脑到云上解决方案,帮助中小企业更便捷地构建云上办公,并开放无影产品及解决方案能力,为生态合作伙伴提供企业云平台,帮助其打造定制化…

Python小试牛刀:GUI(图形界面)实现计算器UI界面(二)

上一篇:Python小试牛刀:GUI(图形界面)实现计算器UI界面(一)-CSDN博客 在上一篇文章中介绍了Python GUI常用的库,以及运用GUI标准库tkinter仅设计了计算器的UI界面。 而在本篇文章,…

「Java开发指南」如何用MyEclipse搭建Spring MVC应用程序?(一)

本教程将指导开发者如何生成一个可运行的Spring MVC客户应用程序,该应用程序实现域模型的CRUD应用程序模式。在本教程中,您将学习如何: 从数据库表的Scaffold到现有项目部署搭建的应用程序 使用Spring MVC搭建需要MyEclipse Spring或Bling授…

本章内容的重点是对各种电子式电动机保护器电路的原理分析和故障维修指导,对电子式电动机保护器以下简称为电动机保护器。

上世纪八十年代之前,电子技术的应用尚处于初级阶段,对电动机的保护任务多由热继电器承担,国内型号为为JR20-XX系列、JR36-XX系列等。其保护机理如下:热继电器由发热元件、双金属片、触点及一套传动和调整机构组成。发热元件是一段…