更新记录
1.0.0(2026-09-29)
- 实现录屏投屏直播 RTMP 推流
- 新增 initRtmpEngine / startScreenStream / getStreamStats / stopScreenStream
- 原生胶水层统一参数兜底(屏幕尺寸取偶、30fps、自适应码率 1~8Mbps、关键帧 2s、44100Hz / 1ch / 64000bps)
平台兼容性
uni-app(4.72)
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| √ |
√ |
× |
× |
√ |
√ |
5.0 |
× |
× |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| × |
× |
× |
× |
× |
× |
× |
× |
× |
× |
× |
× |
uni-app x(4.72)
| Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
| × |
× |
5.0 |
× |
× |
× |
zy-rtmp-screen
手机录屏投屏直播 RTMP 推流插件(仅 Android 5.0+)。
MediaProjection 采集整屏画面 + H.264/AAC 硬编码 + 原生 RTMP 推流 + 前台服务常驻,可选叠加麦克风。
使用
import { initRtmpEngine, startScreenStream, getStreamStats, stopScreenStream } from '@/uni_modules/zy-rtmp-screen'
四个 API 均为异步回调,支持 success / fail / complete。
| API |
作用 |
initRtmpEngine() |
初始化引擎(可省,开始推流时自动初始化) |
startScreenStream(options) |
开始推流,授权通过并启动成功后回调 success |
getStreamStats() |
查询状态与统计,不中断推流 |
stopScreenStream() |
停止推流并释放资源 |
startScreenStream 只有 rtmpUrl 必填,其余全可省略:
| 参数 |
说明 |
缺省值 |
rtmpUrl |
rtmp:// 开头的推流地址 |
必填 |
width / height |
分辨率 |
屏幕尺寸 |
videoBitrate |
视频码率 bps |
按分辨率 1~8Mbps |
fps / iframeInterval |
帧率 / 关键帧间隔(秒) |
30 / 2 |
audioEnabled |
是否采麦克风 |
true |
audioBitrate / audioSampleRate / audioChannels |
音频码率 / 采样率 / 声道 |
64000 / 44100 / 1 |
notificationTitle / notificationContent |
通知文案 |
应用名 |
错误码 9050001~9050013 经 fail(err.errCode, err.errMsg) 返回,常见:9050002 非自定义基座、9050004/5 权限被拒、9050006 连接失败(地址/密钥)、9050008 采集失败。
示例
<template>
<view>
<button :disabled="streaming" @click="doStart">开始投屏直播</button>
<button :disabled="!streaming" @click="doStop">停止推流</button>
<view>{{ statusText }} · {{ stats.connected ? '在线' : '离线' }} ·
{{ stats.bytesSent }}B · {{ stats.frameCount }}帧 / {{ stats.fps }}fps</view>
</view>
</template>
<script>
import { initRtmpEngine, startScreenStream, getStreamStats, stopScreenStream } from '@/uni_modules/zy-rtmp-screen'
export default {
data() {
return { streaming: false, statusText: '未推流', timer: null,
stats: { connected: false, bytesSent: 0, frameCount: 0, fps: 0 } }
},
onLoad() { initRtmpEngine({ fail: (e) => uni.showToast({ title: e.errMsg, icon: 'none' }) }) },
onUnload() { this.clearTimer() },
methods: {
clearTimer() { if (this.timer) { clearInterval(this.timer); this.timer = null } },
refresh() {
getStreamStats({
success: (res) => {
this.stats = res
if (!res.streaming && this.streaming) {
this.streaming = false; this.statusText = '已断开'; this.clearTimer()
}
}
})
},
doStart() {
startScreenStream({
rtmpUrl: 'rtmp://your-server/live/stream',
width: 720, height: 1280, videoBitrate: 2000000, fps: 24, audioEnabled: true,
success: (res) => {
this.streaming = true
this.statusText = `推流中 ${res.width}x${res.height}`
this.clearTimer()
this.timer = setInterval(() => this.refresh(), 1000)
},
fail: (err) => {
this.streaming = false; this.statusText = '未推流'
uni.showToast({ title: err.errCode + ': ' + err.errMsg, icon: 'none' })
}
})
},
doStop() {
stopScreenStream({
success: () => { this.streaming = false; this.statusText = '未推流'; this.clearTimer() },
fail: (err) => console.log(err)
})
}
}
}
</script>