1.0.1 • Published 1 month ago

@tanzhenxing/zx-live-pusher v1.0.1

Weekly downloads
-
License
ISC
Repository
-
Last release
1 month ago

zx-live-pusher 直播推流组件

zx-live-pusher 是基于 uni-app 官方 live-pusher 组件封装的增强版直播推流组件,提供了更简单的接口和更丰富的功能。

平台兼容性

AppH5微信小程序其他小程序
√(nvue)、vue 3.4.1+xx

注意:App平台开发推荐使用nvue,相比vue有更好的性能和更多功能。

使用方法

1. 引入组件

<script>
import ZxLivePusher from '@/components/zx-live-pusher/zx-live-pusher.vue'

export default {
  components: {
    ZxLivePusher
  }
}
</script>

2. 基本用法

<template>
  <view class="content">
    <zx-live-pusher
      ref="livePusher"
      :url="pushUrl"
      mode="HD"
      aspect="9:16"
      :beauty="3"
      :whiteness="3"
      @statechange="onStateChange"
      @netstatus="onNetStatus"
      @error="onError"
    />
    
    <view class="controls">
      <button @click="startLive">开始直播</button>
      <button @click="stopLive">结束直播</button>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      pushUrl: 'rtmp://your-rtmp-server/path'
    }
  },
  methods: {
    startLive() {
      this.$refs.livePusher.startPush();
    },
    stopLive() {
      this.$refs.livePusher.stopPush();
    },
    onStateChange(e) {
      console.log('推流状态变化:', e);
    },
    onNetStatus(e) {
      console.log('网络状态:', e);
    },
    onError(e) {
      console.log('推流错误:', e);
    }
  }
}
</script>

3. 使用内置控制按钮

<zx-live-pusher
  :url="pushUrl"
  :show-controls="true"
  :auto-preview="true"
/>

属性说明

属性名类型默认值说明
urlString''推流地址,支持RTMP协议
modeString'SD'推流视频模式,可选值:SD(标清), HD(高清), FHD(超清)
aspectString'9:16'视频宽高比例
mutedBooleanfalse是否静音
enableCameraBooleantrue开启摄像头
autoFocusBooleantrue自动聚焦
beautyNumber0美颜,取值范围 0-9,0 表示关闭
whitenessNumber0美白,取值范围 0-9,0 表示关闭
orientationString'vertical'画面方向,可选值:vertical, horizontal
minBitrateNumber200最小码率
maxBitrateNumber1000最大码率
audioQualityString'high'音频质量,可选值:high(高音质), low(低音质)
waitingImageString''等待画面图片
waitingImageHashString''等待画面图片的MD5值
zoomBooleanfalse是否启用双指缩放
devicePositionString'front'摄像头位置,可选值:front(前置), back(后置)
backgroundMuteBooleanfalse进入后台时是否静音
remoteMirrorBooleanfalse设置推流画面是否镜像
localMirrorString'auto'设置本地预览画面是否镜像,可选值:auto, enable, disable
audioReverbTypeNumber0音频混响类型,可取值:0 - 7
audioVolumeTypeString'voicecall'音量类型,可选值:media, voicecall
enableMicBooleantrue开启麦克风
enableAgcBooleanfalse是否开启音频自动增益
enableAnsBooleanfalse是否开启音频噪声抑制
audioVolumeTypeSpeakerBooleanfalse扬声器类型
showControlsBooleanfalse是否显示内置控制按钮
autoStartBooleanfalse是否自动开始推流
autoPreviewBooleanfalse是否自动开启预览

事件说明

事件名说明返回参数
statechange推流状态变化事件event.detail: {code, message}
netstatus网络状态通知事件event.detail: 网络状态对象
error推流错误事件event.detail: {errCode, errMsg}
started推流开始事件开始推流的结果
stopped推流停止事件停止推流的结果
paused推流暂停事件暂停推流的结果
resumed推流恢复事件恢复推流的结果
previewStarted预览开始事件开始预览的结果
previewStopped预览停止事件停止预览的结果
cameraSwitched摄像头切换事件切换摄像头的结果
snapshotTaken截图完成事件{tempImagePath: 临时图片路径}
failed推流失败事件失败信息

statechange 事件 code 值说明

code说明
1001已经连接推流服务器
1002已经与服务器握手完毕,开始推流
1003打开摄像头成功
1004录屏启动成功
1005推流动态调整分辨率
1006推流动态调整码率
1007首帧画面采集完成
1008编码器启动
-1301打开摄像头失败
-1302打开麦克风失败
-1303视频编码失败
-1304音频编码失败
-1305不支持的视频分辨率
-1306不支持的音频采样率
-1307网络断连,且经多次重连抢救无效
-1308开始录屏失败,可能是被用户拒绝
-1309录屏失败,不支持的Android系统版本,需要5.0以上的系统
-1310录屏被其他应用打断了
-1311Android Mic打开成功,但是录不到音频数据
-1312录屏动态切横竖屏失败

方法说明

以下方法都返回Promise对象,可以使用async/await或then/catch处理结果。

方法名说明参数返回值
startPush开始推流Promise
stopPush停止推流Promise
pausePush暂停推流Promise
resumePush恢复推流Promise
startPreview开启预览Promise
stopPreview关闭预览Promise
switchCamera切换摄像头Promise
snapshot截图Promise
getContext获取推流上下文LivePusherContext对象

使用示例

直播页面示例

<template>
  <view class="live-page">
    <zx-live-pusher
      ref="livePusher"
      :url="pushUrl"
      mode="HD"
      aspect="9:16"
      :beauty="beautyLevel"
      :whiteness="whitenessLevel"
      @statechange="onStateChange"
      @netstatus="onNetStatus"
      @error="onError"
      @started="onStarted"
      @stopped="onStopped"
    />
    
    <view class="operation-bar">
      <view class="beauty-control">
        <slider :value="beautyLevel" :min="0" :max="9" :step="1" @change="onBeautyChange" show-value />
        <text>美颜</text>
      </view>
      
      <view class="whiteness-control">
        <slider :value="whitenessLevel" :min="0" :max="9" :step="1" @change="onWhitenessChange" show-value />
        <text>美白</text>
      </view>
      
      <view class="buttons">
        <button @click="toggleLive">{{ isLiving ? '结束直播' : '开始直播' }}</button>
        <button @click="takeSnapshot">截图</button>
        <button @click="switchCameraPosition">切换摄像头</button>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      pushUrl: 'rtmp://your-rtmp-server/path',
      beautyLevel: 5,
      whitenessLevel: 5,
      isLiving: false
    }
  },
  onReady() {
    // 页面加载完成后自动开启预览
    this.$refs.livePusher.startPreview();
  },
  methods: {
    async toggleLive() {
      if (this.isLiving) {
        await this.$refs.livePusher.stopPush();
        this.isLiving = false;
      } else {
        try {
          await this.$refs.livePusher.startPush();
          this.isLiving = true;
        } catch (err) {
          uni.showToast({
            title: '开始直播失败',
            icon: 'none'
          });
        }
      }
    },
    
    async takeSnapshot() {
      try {
        const result = await this.$refs.livePusher.snapshot();
        uni.showToast({
          title: '截图成功',
          icon: 'success'
        });
        // 可以在这里处理截图,比如上传或保存
      } catch (err) {
        uni.showToast({
          title: '截图失败',
          icon: 'none'
        });
      }
    },
    
    switchCameraPosition() {
      this.$refs.livePusher.switchCamera();
    },
    
    onBeautyChange(e) {
      this.beautyLevel = e.detail.value;
    },
    
    onWhitenessChange(e) {
      this.whitenessLevel = e.detail.value;
    },
    
    onStateChange(e) {
      const { code, message } = e.detail;
      console.log(`[推流状态] code: ${code}, message: ${message}`);
      
      // 处理特定状态码
      if (code < 0) {
        uni.showToast({
          title: `推流异常: ${message}`,
          icon: 'none'
        });
      }
    },
    
    onNetStatus(e) {
      console.log('[网络状态]', e.detail);
    },
    
    onError(e) {
      console.error('[推流错误]', e.detail);
      uni.showModal({
        title: '推流错误',
        content: `错误码: ${e.detail.errCode}, 错误信息: ${e.detail.errMsg}`,
        showCancel: false
      });
    },
    
    onStarted() {
      uni.showToast({
        title: '开始推流成功',
        icon: 'success'
      });
    },
    
    onStopped() {
      uni.showToast({
        title: '已停止推流',
        icon: 'none'
      });
    }
  }
}
</script>

<style lang="scss">
.live-page {
  position: relative;
  width: 100%;
  height: 100vh;
  
  .operation-bar {
    position: absolute;
    bottom: 40rpx;
    left: 0;
    right: 0;
    padding: 20rpx;
    background-color: rgba(0, 0, 0, 0.3);
    
    .beauty-control,
    .whiteness-control {
      margin-bottom: 20rpx;
      
      text {
        color: #fff;
        font-size: 24rpx;
        margin-left: 10rpx;
      }
    }
    
    .buttons {
      display: flex;
      justify-content: space-around;
      
      button {
        flex: 1;
        margin: 0 10rpx;
        font-size: 28rpx;
        height: 70rpx;
        line-height: 70rpx;
      }
    }
  }
}
</style>

注意事项

  1. 在App平台使用本组件,需要在 manifest.json 中勾选 LivePusher(直播推流) 模块。
  2. live-pusher 是原生组件,在小程序中层级最高,需要使用 cover-view 覆盖。
  3. 在App端的nvue页面中使用时没有层级限制。
  4. 推流前需要确保有可用的网络连接,且用户已授予相机和麦克风权限。
  5. 如需在安卓后台继续推流,请配置应用为前台服务。

常见问题

1. 推流地址格式

推流地址一般为RTMP格式,例如:rtmp://domain/app/stream

2. 获取不到摄像头/麦克风权限

确保已经在应用中申请了相机和麦克风权限,可以在组件挂载前先调用权限申请API:

onLoad() {
  // 请求相机权限
  uni.authorize({
    scope: 'scope.camera',
    success() {
      console.log('相机权限已获取');
    },
    fail() {
      uni.showModal({
        title: '提示',
        content: '请允许使用摄像头权限',
        showCancel: false
      });
    }
  });
  
  // 请求麦克风权限
  uni.authorize({
    scope: 'scope.record',
    success() {
      console.log('麦克风权限已获取');
    },
    fail() {
      uni.showModal({
        title: '提示',
        content: '请允许使用麦克风权限',
        showCancel: false
      });
    }
  });
}

3. 如何处理网络异常

可以在netstatus事件中监控网络状态,当检测到网络异常时,可以尝试重新连接或提示用户:

onNetStatus(e) {
  const info = e.detail;
  
  // 检测网络质量
  if (info.netSpeed < 100) { // 网速过低
    uni.showToast({
      title: '网络状况不佳,请检查网络连接',
      icon: 'none'
    });
  }
  
  // 也可以根据videoBitrate等参数动态调整画质
  if (info.videoBitrate < 200) {
    // 可以考虑降低画质
    // this.mode = 'SD';
  }
}

更多资源