mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-16 02:44:51 +00:00
Add jassub/libpgs support on the web
This commit is contained in:
+35
-5
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import type React from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
|
||||
import {
|
||||
OmniProvider,
|
||||
@@ -34,7 +34,6 @@ const PLAYLIST = [
|
||||
},
|
||||
] as const;
|
||||
|
||||
|
||||
function formatTime(seconds: number): string {
|
||||
if (!Number.isFinite(seconds) || seconds < 0) {
|
||||
return "00:00";
|
||||
@@ -217,7 +216,21 @@ function PlayerExample({
|
||||
<Text style={styles.heading}>react-native-omni</Text>
|
||||
<Text style={styles.subheading}>{trackLabel}</Text>
|
||||
|
||||
<OmniView style={styles.video} autoplay={true} showNotification={true} />
|
||||
<OmniView
|
||||
style={styles.video}
|
||||
autoplay={true}
|
||||
showNotification={true}
|
||||
subtitleAssets={{
|
||||
// The worker is bundled by webpack; only the wasm binaries and the
|
||||
// fallback font are self-hosted (see webpack devServer.static).
|
||||
jassub: {
|
||||
wasmUrl: "/jassub/jassub-worker.wasm",
|
||||
modernWasmUrl: "/jassub/jassub-worker-modern.wasm",
|
||||
fontUrl: "/jassub/default.woff2",
|
||||
},
|
||||
pgs: { workerUrl: "/pgs/libpgs.worker.js" },
|
||||
}}
|
||||
/>
|
||||
|
||||
<View style={styles.row}>
|
||||
<Pressable style={styles.button} onPress={togglePlayback}>
|
||||
@@ -381,7 +394,10 @@ function PlayerExample({
|
||||
isAutoQuality && styles.selectedTrackButtonText,
|
||||
]}
|
||||
>
|
||||
Auto{isAutoQuality && tracks.renditions.find(r => r.selected) ? ` (${tracks.renditions.find(r => r.selected)!.height}p)` : ""}
|
||||
Auto
|
||||
{isAutoQuality && tracks.renditions.find((r) => r.selected)
|
||||
? ` (${tracks.renditions.find((r) => r.selected)!.height}p)`
|
||||
: ""}
|
||||
</Text>
|
||||
</Pressable>
|
||||
{tracks.renditions.length === 0 ? (
|
||||
@@ -449,7 +465,21 @@ function App(): React.JSX.Element {
|
||||
headers: {},
|
||||
},
|
||||
],
|
||||
subtitles: [],
|
||||
subtitles: [
|
||||
{
|
||||
id: "kusu",
|
||||
link: "https://jassub.pages.dev/subtitles/Kusriya%20S2%20OP1v3.ass",
|
||||
},
|
||||
{
|
||||
id: "pgs",
|
||||
link: "https://raw.githubusercontent.com/Arcus92/libpgs-js/main/tests/files/test.sup",
|
||||
label: "PGS test",
|
||||
},
|
||||
],
|
||||
fonts: [
|
||||
"https://jassub.pages.dev/fonts/FOT-TsukuCOldMinPr6NR.OTF",
|
||||
"https://jassub.pages.dev/fonts/arial.ttf",
|
||||
],
|
||||
metadata: {
|
||||
title: PLAYLIST[currentIndex].title,
|
||||
artist: PLAYLIST[currentIndex].artist,
|
||||
|
||||
Binary file not shown.
+92
-61
@@ -5,65 +5,96 @@ const appDirectory = path.resolve(__dirname);
|
||||
const rootDirectory = path.resolve(__dirname, "..");
|
||||
|
||||
module.exports = {
|
||||
mode: "development",
|
||||
devtool: "eval-source-map",
|
||||
entry: path.resolve(__dirname, "index.web.js"),
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "bundle.web.js",
|
||||
publicPath: "/",
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".web.tsx", ".web.ts", ".tsx", ".ts", ".web.js", ".js"],
|
||||
alias: {
|
||||
"react-native$": "react-native-web",
|
||||
"react-native-omni": path.resolve(rootDirectory, "src"),
|
||||
react: path.resolve(appDirectory, "node_modules", "react"),
|
||||
"react-dom": path.resolve(appDirectory, "node_modules", "react-dom"),
|
||||
},
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|ts|tsx)$/,
|
||||
exclude: /node_modules\/(?!(react-native|@react-native|react-native-web|react-native-omni)\/).*/,
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
plugins: [
|
||||
["@babel/plugin-transform-react-jsx", { runtime: "automatic" }],
|
||||
[
|
||||
"module-resolver",
|
||||
{
|
||||
extensions: [".js", ".ts", ".json", ".jsx", ".tsx"],
|
||||
alias: {
|
||||
"react-native-omni": path.resolve(rootDirectory, "src"),
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)$/i,
|
||||
type: "asset/resource",
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(__dirname, "public/index.html"),
|
||||
}),
|
||||
],
|
||||
devServer: {
|
||||
port: 3000,
|
||||
hot: true,
|
||||
historyApiFallback: true,
|
||||
},
|
||||
mode: "development",
|
||||
devtool: "eval-source-map",
|
||||
entry: path.resolve(__dirname, "index.web.js"),
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "bundle.web.js",
|
||||
publicPath: "/",
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".web.tsx", ".web.ts", ".tsx", ".ts", ".web.js", ".js"],
|
||||
alias: {
|
||||
"react-native$": "react-native-web",
|
||||
"react-native-omni": path.resolve(rootDirectory, "src"),
|
||||
react: path.resolve(appDirectory, "node_modules", "react"),
|
||||
"react-dom": path.resolve(appDirectory, "node_modules", "react-dom"),
|
||||
},
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|ts|tsx)$/,
|
||||
exclude:
|
||||
/node_modules\/(?!(react-native|@react-native|react-native-web|react-native-omni)\/).*/,
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: [
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
plugins: [
|
||||
["@babel/plugin-transform-react-jsx", { runtime: "automatic" }],
|
||||
[
|
||||
"module-resolver",
|
||||
{
|
||||
extensions: [".js", ".ts", ".json", ".jsx", ".tsx"],
|
||||
alias: {
|
||||
"react-native-omni": path.resolve(rootDirectory, "src"),
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)$/i,
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
// Disable webpack's `new URL(..., import.meta.url)` asset emission for
|
||||
// jassub. jassub references a `./default.woff2` it does not ship (which
|
||||
// would fail the build) and its wasm URLs; we self-host the wasm + font
|
||||
// and pass them via `subtitleAssets` instead. The worker itself is still
|
||||
// bundled (that goes through `new Worker(new URL(...))`, not this rule).
|
||||
test: /[\\/]jassub[\\/]/,
|
||||
parser: { url: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(__dirname, "public/index.html"),
|
||||
}),
|
||||
],
|
||||
devServer: {
|
||||
port: 3000,
|
||||
hot: true,
|
||||
historyApiFallback: true,
|
||||
// jassub's wasm is multithreaded (pthreads), which needs SharedArrayBuffer
|
||||
// and therefore a cross-origin-isolated page. `credentialless` keeps
|
||||
// cross-origin video/subtitle/font requests working without CORP headers.
|
||||
headers: {
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
"Cross-Origin-Embedder-Policy": "credentialless",
|
||||
},
|
||||
// Host the ASS/PGS subtitle renderer assets under `/jassub` and `/pgs`.
|
||||
// jassub/libpgs ship the worker + wasm; `public/jassub/default.woff2`
|
||||
// provides the fallback font jassub does not bundle.
|
||||
static: [
|
||||
{ directory: path.resolve(appDirectory, "public") },
|
||||
{
|
||||
directory: path.resolve(rootDirectory, "node_modules/jassub/dist/wasm"),
|
||||
publicPath: "/jassub",
|
||||
},
|
||||
{
|
||||
directory: path.resolve(rootDirectory, "node_modules/libpgs/dist"),
|
||||
publicPath: "/pgs",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user