# 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 install
The 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 删除。