如何快速集成NodeMediaClient-Harmony

NodeMediaClient-harmony是一个适用于OpenHarmony_5.0 / HarmonyOS_NEXT 平台的低延迟直播播放组。支持RTSP、RTMP、HTTP-FLV、HLS、KMP等流媒体协议的播放。下面将介绍如何将NodeMediaClient-harmony集成到您的HarmonyOS应用中。

特性

·支持RTSP,RTMP(S),HTTP(S)_FLV,HLS,KMP,UDP_MPEGTS等协议。 ·支持H.264/H.265视频硬件解码渲染 ·支持AAC/G.711音频解码播放 ·毫秒级低延迟 ·延迟消除

创建项目

SDK根据项目选择,现阶段推荐5.0.0(12)

安装依赖

使用DevEco打开项目后,点击下方Terminal,输入命令安装依赖

bash 复制代码
ohpm install @nodemedia/nodemediaclient

引用播放组件

kotlin 复制代码
// 导入NodePlayer播放器组件及其控制器
import { NodePlayer, NodePlayerController } from '@nodemedia/nodemediaclient'

// 使用@Entry装饰器标记为页面入口组件
// @Component表示这是一个自定义组件
@Entry
@Component
struct VideoPlayerPage {
  // ============= 播放器配置参数 =============
  @State src: string = 'https://live.nodemedia.cn:8443/live/b480_264.flv' // 默认视频流地址
  @State volume: number = 10 // 音量值(范围0-10)
  @State muted: boolean = false // 静音开关状态
  @State bufferTime: number = 1000 // 视频缓冲时间(毫秒)
  @State scaleMode: number = 1 // 画面缩放模式:0=填充 1=适应 2=拉伸
  @State isPlaying: boolean = false // 当前是否正在播放
  @State statusText: string = '准备播放' // 播放器状态显示文本
  // 播放器控制器实例
  private controller: NodePlayerController = new NodePlayerController()
  // ============= 播放器事件回调 =============
  private onPlayerEvent: (code: number, msg: string) => void = (code: number, msg: string) => {
    console.info(`[PlayerEvent] code=${code}, msg=${msg}`);

    switch (code) {
      // ===== 播放相关事件 =====
      case 1000: // 正在连接视频
        this.statusText = '连接中...';
        this.isPlaying = false;
        break;

      case 1001: // 视频连接成功
        this.statusText = '正在播放';
        this.isPlaying = true;
        break;

      case 1002: // 视频连接失败(自动重连中)
        this.statusText = '连接失败,自动重连中...';
        this.isPlaying = false;
        break;

      case 1003: // 视频开始重连
        this.statusText = '正在重新连接...';
        break;

      case 1004: // 视频播放结束
        this.statusText = '播放结束';
        this.isPlaying = false;
        break;

      case 1005: // 网络异常(自动重连中)
        this.statusText = '网络异常,自动重连中...';
        break;

      case 1006: // 网络连接超时(自动重连中)
        this.statusText = '连接超时,自动重连中...';
        break;

    // ===== 缓冲相关事件 =====
      case 1100: // 播放缓冲区为空

        break;

      case 1101: // 播放缓冲区正在缓冲数据

        break;

      case 1102: // 缓冲完成,开始播放

        break;

      case 1103: // 流统计信息(每秒回调)

        break;

      case 1104: // 解码后得到视频高宽(格式为 width x height)

        break;

    }
  };

  // ============= 构建UI布局 =============
  build() {
    // 主容器(垂直布局)

    Column() {
      // ----------------- 播放器标题 -----------------
      Text('NodePlayer')
        .fontSize(36)
        .fontWeight('Bolder')
        .margin(20)
      // ----------------- 播放器视图 -----------------
      NodePlayer({
        license: '', // 授权许可(测试可为空)
        src: this.src, // 视频源地址
        scaleMode: this.scaleMode, // 画面缩放模式
        bufferTime: this.bufferTime, // 缓冲时间设置
        controller: this.controller, // 控制器实例
        muted: this.muted, // 静音状态
        volume: this.volume / 10, // 音量转换(0.0-1.0范围)
        autoplay: false, // 是否自动播放
        onEvent: this.onPlayerEvent // 事件回调绑定
      })
        .width('100%')// 宽度撑满
        .height(300)// 固定高度
        .backgroundColor('#000000') // 黑色背景

      // ----------------- 状态显示文本 -----------------
      Text(this.statusText)
        .fontSize(16)// 字体大小
        .margin(10) // 外边距

      // ----------------- URL输入框 -----------------
      TextInput({ text: this.src })
        .width('90%')// 相对宽度
        .height(40)// 固定高度
        .margin(10)// 外边距
        .onChange((value: string) => {
          this.src = value // 实时更新视频源地址
        })

      // ----------------- 控制按钮行 -----------------
      Row() {
        // 播放按钮
        Button('播放')
          .onClick(() => {

            if (this.statusText == '已暂停') {
              this.statusText = '连接成功,开始播放'
              this.controller.start() // 调用播放器开始播放
            } else {
              this.controller.start() // 调用播放器开始播放
            }
          })
          .margin(5) // 按钮间距

        // 暂停按钮
        Button('暂停')
          .onClick(() => {
            if (this.isPlaying == true) {
              this.controller.pause() // 调用播放器暂停
              this.statusText = '已暂停' // 立即更新状态文本
            }

          })
          .margin(5)

        // 停止按钮
        Button('停止')
          .onClick(() => {
            this.controller.stop() // 调用播放器停止
            this.statusText = '已停止' // 更新状态文本
          })
          .margin(5)
      }

      // ----------------- 音效控制区域 -----------------
      Column() {
        // 静音开关行
        Row() {
          Text('静音')// 标签文本
            .margin({ right: 10 }) // 右间距
          Toggle({ type: ToggleType.Switch, isOn: this.muted })
            .onChange((isOn: boolean) => {
              this.muted = isOn // 更新静音状态
            })
        }
        .width('100%') // 宽度撑满
        .justifyContent(FlexAlign.Start) // 左对齐
        .margin(5) // 外边距

        // 音量滑块行
        Row() {
          Text('音量')// 标签文本
            .margin({ right: 10 })
          Slider({
            value: this.volume,
            min: 0, // 最小值
            max: 10, // 最大值
            step: 1, // 步长
            style: SliderStyle.OutSet // 滑块样式
          })
            .onChange((value: number) => {
              this.volume = value // 更新音量值
              if (value > 0) {
                this.muted = false // 音量>0时自动关闭静音
              }
            })
            .width('60%') // 滑块宽度
          Text(this.volume.toString())// 音量数值显示
            .margin({ left: 10 })
            .width(20) // 固定宽度
        }
        .width('100%')
        .margin(5)
      }
      .width('100%')
      .margin(10)

      // ----------------- 缩放模式选择 -----------------
      Column() {
        // 将标题和选项放在同一个Row中
        Row() {
          // 标题文本(左侧)
          Text('缩放模式:')
            .fontSize(16)
            .margin({ right: 15 })// 右边距与选项分隔
            .alignSelf(ItemAlign.Center) // 垂直居中

          // 选项组(右侧)
          Row() {
            // 填充模式
            Column() {
              Radio({ value: 'Radio0', group: 'ScaleMode' })
                .checked(this.scaleMode === 0)
                .onChange((isChecked: boolean) => {
                  if (isChecked) {
                    this.scaleMode = 0
                  }
                })
                .margin(5)
              Text('填充')
                .fontSize(14)
            }
            .margin({ right: 15 })

            // 适应模式
            Column() {
              Radio({ value: 'Radio1', group: 'ScaleMode' })
                .checked(this.scaleMode === 1)
                .onChange((isChecked: boolean) => {
                  if (isChecked) {
                    this.scaleMode = 1
                  }
                })
                .margin(5)
              Text('适应')
                .fontSize(14)
            }
            .margin({ right: 15 })

            // 拉伸模式
            Column() {
              Radio({ value: 'Radio2', group: 'ScaleMode' })
                .checked(this.scaleMode === 2)
                .onChange((isChecked: boolean) => {
                  if (isChecked) {
                    this.scaleMode = 2
                  }
                })
                .margin(5)
              Text('拉伸')
                .fontSize(14)
            }
          }
          .alignItems(VerticalAlign.Center) // 选项组垂直居中
        }
        .width('100%')
        .justifyContent(FlexAlign.Start) // 整体左对齐
      }
      .width('100%')
      .margin(10)
    }
    // 页面容器样式
    .width('100%') // 宽度撑满
    .height('100%') // 高度撑满
    .padding(10) // 内边距
    .alignItems(HorizontalAlign.Center) // 子项水平居中
  }
}

必须打开网络权限,在module.json5中加入以下代码

json 复制代码
        "requestPermissions": [
          {
            "name": "ohos.permission.INTERNET"
          }
        ],

低延迟: 使用OBS实时推流时间页面到本地NodeMediaServer,使用NodeMediaClient播放,buffertime设置100ms,手机拍照对比时间差值为320ms。

高性能: 在华为Mate 60 Pro 手机上播放4K H.264视频

多路流同时播放: 在华为Mate 60 Pro 中同时播放9路1080P H.264视频

相关推荐
鸿蒙布道师8 小时前
鸿蒙NEXT开发Base64工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
The 旺9 小时前
《HarmonyOS Next开发实战:从零构建响应式Todo应用的基石》
华为·harmonyos
Industio_触觉智能10 小时前
鸿蒙北向开发OpenHarmony5.0 DevEco Studio开发工具安装与配置
harmonyos·鸿蒙系统·openharmony·开源鸿蒙·鸿蒙开发·嵌入式开发板
秋叶先生_14 小时前
HarmonyOS NEXT——【鸿蒙监听网络状态变化】
华为·harmonyos·鸿蒙
东林知识库15 小时前
鸿蒙NEXT小游戏开发:围住神经猫
harmonyos
zacksleo15 小时前
鸿蒙Flutter开发故事:不,你不需要鸿蒙化
flutter·harmonyos
别说我什么都不会17 小时前
OpenHarmony解读之设备认证:sts协议-客户端发起sts end请求
物联网·嵌入式·harmonyos
悬空八只脚20 小时前
React-Native开发鸿蒙NEXT-本地与沙盒加载bundle
harmonyos
鸿蒙布道师20 小时前
鸿蒙NEXT开发日志工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
90后的晨仔20 小时前
HarmonyOS的页面生命周期 和 组件生命周期
harmonyos