首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >云点播react-native版(Android版本优化中)

云点播react-native版(Android版本优化中)

原创
作者头像
用户2495556
修改2025-10-21 18:40:54
修改2025-10-21 18:40:54
190
举报

# 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

代码语言:sh
复制
yarn add react-native-txc-player

# or

npm install react-native-txc-player

### iOS

代码语言:sh
复制
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:

代码语言:ts
复制
import { setTXCLicense } from 'react-native-txc-player';

setTXCLicense('https://your-license-url', 'your-license-key');

## Usage

代码语言:tsx
复制
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

代码语言:ts
复制
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:

代码语言:json
复制
{

 "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.

代码语言:sh
复制
yarn install

yarn example ios # or `yarn example android`

## License

MIT


Made with create-react-native-library

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档