如何快速集成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视频

相关推荐
亚历克斯神4 小时前
Flutter for OpenHarmony: Flutter 三方库 mutex 为鸿蒙异步任务提供可靠的临界资源互斥锁(并发安全基石)
android·数据库·安全·flutter·华为·harmonyos
钛态4 小时前
Flutter 三方库 smartstruct 鸿蒙化字段映射适配指南:介入静态预编译引擎扫除视图及数据模型双向强转类型错乱隐患,筑稳如磐石的企业级模型治理防线-适配鸿蒙 HarmonyOS ohos
flutter·华为·harmonyos
键盘鼓手苏苏4 小时前
Flutter 组件 csv2json 适配鸿蒙 HarmonyOS 实战:高性能异构数据转换,构建 CSV 流式解析与全栈式数据映射架构
flutter·harmonyos·鸿蒙·openharmony
雷帝木木4 小时前
Flutter 三方库 hrk_logging 的鸿蒙化适配指南 - 实现标准化分层日志记录、支持多目的地输出与日志分级过滤
flutter·harmonyos·鸿蒙·openharmony·hrk_logging
左手厨刀右手茼蒿4 小时前
Flutter 三方库 dio_compatibility_layer 的鸿蒙化适配指南 - 实现 Dio 跨主版本的平滑迁移、支持遗留拦截器兼容与网络请求架构稳定升级
flutter·harmonyos·鸿蒙·openharmony·dio_compatibility_layer
雷帝木木4 小时前
Flutter 三方库 hashids2 基于鸿蒙安全内核的深度隐匿映射适配:数字指纹泄露防御层、生成短小精悍唯一不可逆加盐哈希,护航全链路请求 URL 隐私-适配鸿蒙 HarmonyOS ohos
安全·flutter·harmonyos
HwJack206 小时前
HarmonyOS响应式布局与窗口监听:让界面像呼吸般灵动的艺术
ubuntu·华为·harmonyos
王码码20357 小时前
Flutter 组件 inappwebview_cookie_manager 适配 鸿蒙Harmony 实战 - 驾驭核心大 Web 容器缓存隧道、构建金融级政企应用绝对防串号跨域大隔离基座
flutter·harmonyos·鸿蒙·openharmony·inappwebview_cookie_manager
左手厨刀右手茼蒿7 小时前
Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 驾驭企业级 Exchange Web Services 协议、实现鸿蒙端政企办公同步与高安通讯隔离方案
flutter·harmonyos·鸿蒙·openharmony
键盘鼓手苏苏7 小时前
Flutter 组件 spry 适配鸿蒙 HarmonyOS 实战:轻量化 Web 框架,构建高性能端侧微服务与 Middleware 治理架构
flutter·harmonyos·鸿蒙·openharmony