
# react-native-txc-player
React Native Fabric view that wraps Tencent Cloud SuperPlayer for iOS and Android. It provides a declarative API for SuperPlayer UI features such as hiding built-in controls, feeding cover artwork, dynamic/ghost watermarks, and injecting external subtitles.
The player automatically releases its native resources when the React component unmounts to avoid GC pressure on Android.
## Installation
yarn add react-native-txc-player
# or
npm install react-native-txc-player### iOS
cd ios && pod installThe iOS target links the SuperPlayer CocoaPod and requires that you set a licence before playback (see Licence below).
### Android
No manual steps are required. The library pulls in com.tencent.liteav:LiteAVSDK\_Player and registers a Fabric view. If you work behind a firewall that blocks Tencent's Maven mirror, add a mirror that can resolve LiteAVSDK\_Player to your root Gradle repositories.
## Licence
Before mounting the player, initialise the LiteAV SDK licence exactly once in your app lifecycle:
import { setTXCLicense } from 'react-native-txc-player';
setTXCLicense('https://your-license-url', 'your-license-key');## Usage
import { useEffect, useRef, useState } from 'react';
import { View, StyleSheet, Alert, Text, Pressable } from 'react-native';
import {
setTXCLicense,
TxcPlayerView,
Commands,
type TxcPlayerViewRef,
} from 'react-native-txc-player';
export default function App() {
const ref = useRef<TxcPlayerViewRef>(null);
const [ready, setReady] = useState(false);
const [isPlaying, setIsPlaying] = useState(true);
const [position, setPosition] = useState(0);
const [duration, setDuration] = useState(0);
useEffect(() => {
setTXCLicense(
'',
''
);
setReady(true);
setIsPlaying(true);
}, []);
// 2) 只有 ready 才渲染播放器(防止先渲染后设置导致校验失败)
return (
<View style={{ flex: 1, backgroundColor: '#000' }}>
{ready ? (
<>
<Pressable
onPress={() => {
if (!ref.current) return;
if (isPlaying) {
Commands.pause(ref.current);
} else {
Commands.resume(ref.current);
}
setIsPlaying(!isPlaying);
}}
style={styles.box}
>
<TxcPlayerView
ref={ref}
autoplay
source={{
appId: '',
fileId: '',
psign:
'',
}}
config={{
hideFullscreenButton: true,
hideFloatWindowButton: true,
hidePipButton: true,
hideBackButton: true,
hideResolutionButton: true,
hidePlayButton: true,
hideProgressBar: true,
autoHideProgressBar: true,
disableDownload: true,
maxBufferSize: 120,
maxPreloadSize: 20,
coverUrl: 'https://main.qcloudimg.com/raw/9a3f830b73fab9142c078f2c0c666cce.png',
}}
onPlayerEvent={(e: any) => {
const evt = e.nativeEvent;
console.log('[TXC event]', evt);
if (evt.type === 'begin' || evt.type === 'firstFrame') {
setIsPlaying(true);
}
if (evt.type === 'end' || evt.type === 'error') {
setIsPlaying(false);
}
if (evt.type === 'progress') {
if (typeof evt.position === 'number') {
setPosition(evt.position);
}
if (typeof evt.duration === 'number') {
setDuration(evt.duration);
}
}
if (evt.type === 'error') {
Alert.alert(
'播放错误',
`code=${evt.code}, message=${evt.message}`
);
}
}}
style={StyleSheet.absoluteFill}
/>
</Pressable>
</>
) : (
<Text style={{ color: '#fff' }}>正在初始化 License…</Text>
)}
<Text style={{ color: '#fff', padding: 12 }}>
{`当前位置: ${position.toFixed(1)}s / ${duration > 0 ? duration.toFixed(1) : '??'}s`}
</Text>
<View style={styles.controls}>
<Pressable
onPress={() => {
if (!ref.current) return;
Commands.seek(ref.current, 0);
}}
style={styles.seekButton}
>
<Text style={styles.seekButtonText}>Seek 0s</Text>
</Pressable>
<Pressable
onPress={() => {
if (!ref.current) return;
const target = duration > 0 ? Math.min(position + 15, duration) : position + 15;
Commands.seek(ref.current, target);
}}
style={styles.seekButton}
>
<Text style={styles.seekButtonText}>+15s</Text>
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
box: {
flex: 1,
marginVertical: 20,
},
controls: {
flexDirection: 'row',
justifyContent: 'center',
paddingBottom: 24,
paddingHorizontal: 16,
},
seekButton: {
paddingHorizontal: 16,
paddingVertical: 8,
borderRadius: 6,
backgroundColor: 'rgba(255,255,255,0.15)',
marginHorizontal: 8,
},
seekButtonText: {
color: '#fff',
fontWeight: '600',
},
});## Props
| Prop | Type | Description |
| --- | --- | --- |
| autoplay | boolean | Autoplay when a new source is assigned. Defaults to false. |
| source | { url?: string; appId?: string; fileId?: string; psign?: string } | Either pass a direct URL **or** a VOD fileId with the corresponding appId/psign. |
| config | PlayerConfig | Optional UI/runtime tweaks (see below). |
| onPlayerEvent | (event) => void | Receives events such as begin, firstFrame, progress, end, loadingEnd, error, subtitleNotice. The payload also contains code/message when available. |
PlayerConfig
| Field | Type | Notes |
| --- | --- | --- |
| hideFullscreenButton (hideFullScreenButton) | boolean | Hides the fullscreen button in the native SuperPlayer UI (iOS). Android uses a custom overlay, so the flag is informational only. |
| hideFloatWindowButton | boolean | Disables the floating-window control on iOS and prevents the Android view from attempting to enter float mode. |
| hidePipButton | boolean | Hides the Picture-in-Picture button and force-disables automatic PiP. |
| hideBackButton | boolean | Hides the back button in the default SuperPlayer control overlay (iOS only). |
| hideResolutionButton | boolean | Hides the clarity/resolution switcher button in the default SuperPlayer controls (iOS only). |
| hidePlayButton | boolean | Hides the central play/pause button that sits to the left of the progress slider (iOS only). |
| hideProgressBar | boolean | Completely hides the native progress slider and time labels (iOS only). |
| autoHideProgressBar | boolean | Keeps the SuperPlayer controls auto-hiding (default true). Set to false to pin the progress bar and toolbars on screen. |
| maxBufferSize | number | Maximum forward playback buffer size in MB. Mirrors TXVodPlayConfig.maxBufferSize. |
| maxPreloadSize | number | Maximum preroll/preload buffer size in MB. Mirrors TXVodPlayConfig.maxPreloadSize. |
| disableDownload | boolean | Hides the download button (iOS SuperPlayer UI). |
| coverUrl | string | Remote image displayed until the first video frame renders. |
| dynamicWatermark | { type?: 'dynamic' \| 'ghost'; text: string; duration?: number; fontSize?: number; color?: string } | Adds a moving text watermark overlay. ghost lowers alpha to mimic the official ghost watermark style. duration controls how often the text changes position (seconds). |
| subtitles | Array<{ url: string; name: string; type?: string }> | External subtitle descriptors. iOS forwards them to SuperPlayer. Android surfaces a subtitleNotice event; loading external tracks requires the LiteAV premium package. |
## Commands
import { Commands } from 'react-native-txc-player';
Commands.pause(ref);
Commands.resume(ref);
Commands.reset(ref); // stops and resets the underlying native player
Commands.seek(ref, 42); // jump to 42 seconds (best-effort)## Events
Event payload example:
{
"type": "error",
"code": -2301,
"message": "Network disconnected"
}type values currently emitted: begin, firstFrame, loadingEnd, end, error, warning, subtitleNotice, fullscreenChange, back, and progress.
progress is delivered roughly every 250 ms with the current position, full duration, and buffered amount (buffered) in seconds. Use it to drive custom progress UIs without polling native state.## Android resource management
The Android view registers as a LifecycleEventListener and automatically stops playback, destroys the TXCloudVideoView, and releases the TXVodPlayer when the React view unmounts or the host Activity is destroyed. This mirrors the recommendations in Tencent's documentation to prevent leaked native surfaces and GC pressure.
## Example
The repository ships with an example app (located in the example workspace) that demonstrates licence initialisation, the configuration surface, and tap-to-pause/resume behaviour.
yarn install
yarn example ios # or `yarn example android`## License
MIT
Made with create-react-native-library
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。