海康威视摄像头提供的 ws:// 或 wss:// 格式的视频流,通常是封装了 FLV (Flash Video) 或其他实时流协议的数据。
标准的 React Native 视频播放器(如 react-native-video)和浏览器 <video> 标签一样,本身不支持直接播放 ws:// 协议的 FLV 实时流。
因此,解决方案的核心在于:在 React Native 中找到一个能够解码 ws:// 协议和 FLV 视频格式的播放器库。
核心问题分析
- 协议问题: ws:// (WebSocket) 是一种通信协议,不是像 HTTP 那样的媒体传输协议。视频数据是通过 WebSocket 连接进行传输的。
- 编码问题: WebSocket 传输过来的数据通常是 FLV 格式。你需要一个能实时解码 FLV 的播放器。
- 平台问题: 解决方案必须能在 React Native (iOS 和 Android) 环境下运行。
解决方案:使用react-native-nodemediaclient
目前在 React Native 生态中,处理此类 ws-flv 视频流最成熟、最推荐的库是
react-native-nodemediaclient。
这个库专门为处理实时流媒体而设计,它底层封装了强大的 NodeMediaClient SDK,可以完美地解决你的问题。
为什么推荐
react-native-nodemediaclient?
- 原生支持 ws-flv: 它是为数不多的、能直接在原生端(非 WebView)解码 ws:// 协议下 FLV 视频流的库。
- 高性能: 它使用原生代码进行解码和渲染,性能远超 WebView 方案,可以做到低延迟、高流畅度的播放。
- 功能丰富: 不仅支持播放(pull stream),还支持推流(push stream),即用手机摄像头进行直播。
- 跨平台: 同时支持 iOS 和 Android。
集成步骤
下面是集成
react-native-nodemediaclient 的基本步骤:
1. 安装库
npm install react-native-nodemediaclient --save
# 或者
yarn add react-native-nodemediaclient
2. 链接原生模块
对于较新版本的 React Native (0.60+),自动链接通常会生效。你只需要安装 pods 即可。
cd ios && pod install
对于 Android,通常不需要额外步骤,但请确保你的项目配置正确。
3. 配置权限
视频播放和网络访问需要相应的权限。
- Android (android/app/src/main/AndroidManifest.xml): 确保已声明网络权限。
<uses-permission android:name="android.permission.INTERNET" />
iOS (
ios/YourProject/Info.plist): 通常不需要特殊权限,但如果你需要访问非加密的 ws:// 地址,可能需要配置 App Transport Security。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
4. 在代码中使用播放器
使用起来非常简单,它提供了一个名为 NodePlayerView 的组件。
import React, { useRef } from 'react';
import { View, Button, StyleSheet } from 'react-native';
import { NodePlayerView } from 'react-native-nodemediaclient';
const HikvisionPlayer = () => {
// 替换成你的海康摄像头 ws-flv 地址
const videoStreamUrl = 'ws://your.hikvision.stream.address/path';
const playerRef = useRef(null);
return (
<View style={styles.container}>
<NodePlayerView
style={styles.player}
ref={playerRef}
inputUrl={videoStreamUrl}
scaleMode={'ScaleAspectFit'} // 视频缩放模式
bufferTime={300} // 缓冲时间 (ms)
maxBufferTime={1000} // 最大缓冲时间 (ms)
autoplay={true} // 自动播放
onStatus={(code, msg) => {
// 监听播放器状态
// 例如: 2001=连接中, 2002=连接成功, 2004=播放结束
console.log(`Status: code=${code} msg=${msg}`);
}}
/>
<View style={styles.controls}>
<Button title="停止播放" onPress={() => playerRef.current?.stop()} />
<Button title="开始播放" onPress={() => playerRef.current?.start()} />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000',
},
player: {
flex: 1, // 让播放器占满可用空间
},
controls: {
flexDirection: 'row',
justifyContent: 'space-around',
padding: 10,
},
});
export default HikvisionPlayer;
总结与对比
结论: 对于在 React Native 中播放海康威视提供的 ws:// 视频流的需求,
react-native-nodemediaclient 是目前最直接、最高效的解决方案。
react-native-nodemediaclient 是一个功能强大的流媒体库,主要用于在 React Native 应用中实现直播推流和播放。
下面我将为你全面总结它的用法,涵盖播放器 (NodePlayerView) 和推流器 (NodeCameraView) 两大核心功能,以及它们的详细属性(Props)、方法(Methods)和事件回调(Events)。
一、核心功能概览
react-native-nodemediaclient 主要提供两个 React 组件:
1.NodePlayerView: 用于播放实时或点播视频流。这是你用来播放海康 ws-flv 视频流的组件。2.NodeCameraView: 用于采集摄像头和麦克风数据,并推送到流媒体服务器。也就是直播推流功能。
二、播放器 NodePlayerView 的用法
这是用于消费(观看)视频流的组件。
1. 主要属性 (Props)
属性名 | 类型 | 默认值 | 描述 |
inputUrl | string | - | 【必需】 视频流的地址。支持 rtmp, http-flv, ws-flv 等格式。例如: |
autoplay | boolean | false | 是否在组件加载后自动开始播放。 |
scaleMode | string | ScaleAspectFit | 视频画面的缩放模式。可选值:'ScaleToFill' (拉伸填满), 'ScaleAspectFit' (保持宽高比,黑边填充), 'ScaleAspectFill' (保持宽高比,裁剪填满)。 |
bufferTime | number | 200 | 播放缓冲时间(毫秒)。较小的值可以降低延迟,但可能增加卡顿风险。 |
maxBufferTime | number | 1000 | 最大缓冲时间(毫秒)。网络波动时,播放器最多缓存多长时间的数据。 |
renderType | string | SURFACEVIEW (Android) | 【仅Android】 指定渲染视图类型。可选值:'SURFACEVIEW' (性能更好,但不能做形变和动画), 'TEXTUREVIEW' (性能稍差,但支持动画、透明度等)。 |
audioEnable | boolean | true | 是否开启音频播放。 |
cryptoKey | string | - | 如果视频流经过 AES-128 加密,在此处提供解密密钥。 |
pageEnable | boolean | false | 【仅iOS】 是否开启画中画功能 (Picture-in-Picture)。 |
onStatus | function | - | 【重要】 状态变化时的回调函数,onStatus={(code, msg) => {}}。 |
2. 主要方法 (Methods)
你需要通过 ref 来调用这些方法。
const playerRef = useRef(null);
// <NodePlayerView ref={playerRef} ... />
方法名 | 参数 | 描述 |
start() | - | 开始播放。如果 autoplay 为 false,你需要手动调用此方法。 |
stop() | - | 停止播放并断开连接。 |
pause() | - | 暂停播放。注意:对于实时流(直播),暂停后恢复可能会导致画面跳跃到当前直播时间点。 |
seek(seconds) | number | 跳转到指定的播放时间点(秒)。仅对点播(VOD)视频流有效。 |
3. 状态回调 onStatus
这是监控播放器状态的关键。code 是一个数字,代表不同的事件。
Code | 含义 | 建议操作 |
1000 | 正在连接 | 显示加载动画 |
1001 | 连接成功 | 隐藏加载动画 |
1002 | 连接失败 | 显示重试按钮 |
1003 | 连接断开 | 显示重试按钮 |
1004 | 开始播放 | - |
1005 | 播放结束 | 显示重播按钮 |
1006 | 网络异常 | 提示用户检查网络 |
1102 | 收到视频尺寸 | 可以根据返回的 msg (如 "720x1280") 调整播放器宽高比 |
示例代码:
import React, { useRef } from 'react';
import { View, Button, Text, StyleSheet } from 'react-native';
import { NodePlayerView } from 'react-native-nodemediaclient';
const LivePlayer = ({ streamUrl }) => {
const playerRef = useRef(null);
const [statusText, setStatusText] = React.useState('未连接');
return (
<View style={styles.container}>
<NodePlayerView
style={styles.player}
ref={playerRef}
inputUrl={streamUrl}
scaleMode={'ScaleAspectFit'}
bufferTime={300}
autoplay={true}
onStatus={(code, msg) => {
console.log(`Status: code=${code} msg=${msg}`);
// 在这里根据 code 更新 UI
switch (code) {
case 1000: setStatusText('连接中...'); break;
case 1001: setStatusText('连接成功'); break;
// ... 其他状态
default: setStatusText(`状态: ${code}`);
}
}}
/>
<Text style={styles.status}>{statusText}</Text>
<Button title="停止" onPress={() => playerRef.current?.stop()} />
</View>
);
};
三、推流器 NodeCameraView 的用法
这是用于采集设备音视频并进行直播推流的组件。
1. 主要属性 (Props)
属性名 | 类型 | 默认值 | 描述 |
outputUrl | string | - | 【必需】 推流地址。通常是 RTMP 格式,例如 |
camera | object | { cameraId: 0, cameraFrontMirror: true } | 摄像头配置。cameraId: 0=后置, 1=前置。cameraFrontMirror: 是否开启前置摄像头镜像。 |
audio | object | { bitrate: 32000, profile: 1, samplerate: 44100 } | 音频编码配置。bitrate: 码率, profile: 编码规格, samplerate: 采样率。 |
video | object | { preset: 12, bitrate: 400000, profile: 1, fps: 15, videoFrontMirror: false } | 视频编码配置。preset: 编码预设, bitrate: 码率, profile: 编码规格, fps: 帧率。 |
autopreview | boolean | true | 是否在组件加载后自动开启摄像头预览。 |
denoise | boolean | false | 是否开启音频降噪。 |
dynamicRateEnable | boolean | false | 是否开启动态码率调整。开启后,会根据网络状况自动调整视频码率。 |
onStatus | function | - | 【重要】 推流状态变化的回调函数。 |
2. 主要方法 (Methods)
同样通过 ref 调用。
方法名 | 参数 | 描述 |
startPreview() | - | 开启摄像头预览。 |
stopPreview() | - | 关闭摄像头预览。 |
start() | - | 开始推流。 |
stop() | - | 停止推流。 |
switchCamera() | - | 切换前后摄像头。 |
flashEnable(enable) | boolean | 打开或关闭闪光灯。 |
3. 状态回调 onStatus
推流的状态码与播放器类似,但含义不同。
Code | 含义 |
2000 | 正在连接推流服务器 |
2001 | 连接成功,开始推流 |
2002 | 连接错误 |
2004 | 连接断开 |
2100 | 网络状况不佳,推流不流畅 |
2101 | 网络恢复,推流流畅 |
示例代码:
import React, { useRef, useState } from 'react';
import { View, Button, StyleSheet } from 'react-native';
import { NodeCameraView } from 'react-native-nodemediaclient';
const LivePublisher = ({ streamUrl }) => {
const cameraRef = useRef(null);
const [isPublishing, setIsPublishing] = useState(false);
const handlePublish = () => {
if (isPublishing) {
cameraRef.current?.stop();
setIsPublishing(false);
} else {
cameraRef.current?.start();
setIsPublishing(true);
}
};
return (
<View style={styles.container}>
<NodeCameraView
style={styles.camera}
ref={cameraRef}
outputUrl={streamUrl}
camera={{ cameraId: 1, cameraFrontMirror: true }}
audio={{ bitrate: 32000, profile: 1, samplerate: 44100 }}
video={{ preset: 12, bitrate: 400000, profile: 1, fps: 15, videoFrontMirror: false }}
autopreview={true}
onStatus={(code, msg) => {
console.log(`Publish Status: code=${code} msg=${msg}`);
}}
/>
<Button title="切换摄像头" onPress={() => cameraRef.current?.switchCamera()} />
<Button
title={isPublishing ? '停止直播' : '开始直播'}
onPress={handlePublish}
/>
</View>
);
};
四、总结
o核心用途:该库是 React Native 中处理 RTMP/FLV 直播流 的首选方案。o播放 ws-flv:使用 NodePlayerView,将海康威视的 ws:// 地址直接传入 inputUrl 即可。通过 onStatus 监控状态,通过 ref 控制播放。o直播推流:使用 NodeCameraView,配置好 outputUrl 和音视频参数,通过 ref 控制推流和摄像头。o关键点:
oref 是必须的:所有主动操作(如开始、停止、切换摄像头)都依赖 ref。oonStatus 是核心:所有状态变化(连接、断开、错误)都通过这个回调来获取,是实现健壮播放/推流逻辑的基础。o权限:确保在 Android 和 iOS 上配置了必要的网络和摄像头/麦克风权限。
这份总结涵盖了
react-native-nodemediaclient 的绝大部分常用功能。你可以根据自己的具体需求,查阅这些属性和方法进行开发。
接下来,我们可以:
o深入探讨某个特定属性(如 video 或 audio 的详细配置)如何影响性能和画质。o一起设计一个包含重连、错误提示等功能的更完整的播放器组件。o如果你有推流需求,我们可以讨论如何搭建一个配套的流媒体服务器(如 Node-Media-Server)。