diff --git a/examples/react/src/App.tsx b/examples/react/src/App.tsx index d34b6041..03a69f33 100644 --- a/examples/react/src/App.tsx +++ b/examples/react/src/App.tsx @@ -504,6 +504,12 @@ const App = () => { {renderLoadButton('https://www.tiktok.com/@scout2015/video/6718335390845095173', 'Test B')} + + PeerTube + + {renderLoadButton('https://video.mshparisnord.fr/w/p/aWDVVLYnVGutCDQogoEDf4', 'Test A')} + + Custom diff --git a/package-lock.json b/package-lock.json index ef66be46..83a4aa75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "cloudflare-video-element": "^1.3.4", "dash-video-element": "^0.3.0", "hls-video-element": "^1.5.9", + "peertube-video-element": "^1.1.0", "spotify-audio-element": "^1.0.3", "tiktok-video-element": "^0.1.1", "twitch-video-element": "^0.1.5", @@ -798,6 +799,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "devOptional": true, + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -2451,6 +2453,12 @@ "ce-la-react": "^0.3.0" } }, + "node_modules/media-played-ranges-mixin": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/media-played-ranges-mixin/-/media-played-ranges-mixin-0.1.0.tgz", + "integrity": "sha512-zTsvkleu5sAyTsPVxDI+KUbCwy/lXwHgOPi3ER9S3lhtAWhGTQH6qxvfrVMym1cvoLU36SPbVr6Qe8Zxyc0WpA==", + "license": "MIT" + }, "node_modules/media-tracks": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/media-tracks/-/media-tracks-0.3.4.tgz", @@ -2828,6 +2836,16 @@ "isarray": "0.0.1" } }, + "node_modules/peertube-video-element": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/peertube-video-element/-/peertube-video-element-1.1.0.tgz", + "integrity": "sha512-yQ8X+0X+dZfAD+yLiQJlRdyMHLHr8PB3SQUA49z2heTaLvGDhPzLUJLqOa2NHQbjtVgd5L1z+RBRoBZLlnpplA==", + "license": "MIT", + "dependencies": { + "media-played-ranges-mixin": "^0.1.0", + "media-tracks": "^0.3.0" + } + }, "node_modules/pidtree": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", @@ -2888,6 +2906,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -2899,6 +2918,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" diff --git a/package.json b/package.json index c17ed3b1..456dcee4 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "cloudflare-video-element": "^1.3.4", "dash-video-element": "^0.3.0", "hls-video-element": "^1.5.9", + "peertube-video-element": "^1.1.0", "spotify-audio-element": "^1.0.3", "tiktok-video-element": "^0.1.1", "twitch-video-element": "^0.1.5", diff --git a/src/patterns.ts b/src/patterns.ts index 37809c31..19a60830 100644 --- a/src/patterns.ts +++ b/src/patterns.ts @@ -13,6 +13,8 @@ export const MATCH_URL_WISTIA = export const MATCH_URL_SPOTIFY = /open\.spotify\.com\/(\w+)\/(\w+)/i; export const MATCH_URL_TWITCH = /(?:www\.|go\.)?twitch\.tv\/([a-zA-Z0-9_]+|(videos?\/|\?video=)\d+)($|\?)/; export const MATCH_URL_TIKTOK = /tiktok\.com\/(?:player\/v1\/|share\/video\/|@[^/]+\/video\/)([0-9]+)/; +export const MATCH_URL_PEERTUBE = /(?:videos\/(?:watch|embed)|\/w)\/([^/?#&\s]+)/; + const canPlayFile = (url: string, test: (u: string) => boolean) => { if (Array.isArray(url)) { @@ -42,4 +44,5 @@ export const canPlay = { spotify: (url: string) => MATCH_URL_SPOTIFY.test(url), twitch: (url: string) => MATCH_URL_TWITCH.test(url), tiktok: (url: string) => MATCH_URL_TIKTOK.test(url), + peertube: (url: string)=> MATCH_URL_PEERTUBE.test(url) }; diff --git a/src/players.ts b/src/players.ts index 10a4d1e6..bacb83c9 100644 --- a/src/players.ts +++ b/src/players.ts @@ -93,6 +93,15 @@ const Players: PlayerEntry[] = [ () => import(/* webpackChunkName: 'reactPlayerTiktok' */ 'tiktok-video-element/react') ) as React.LazyExoticComponent>, }, + { + key: 'peertube', + name: 'PeerTube', + canPlay: canPlay.peertube, + canEnablePIP: () => false, + player: lazy( + () => import(/* webpackChunkName: 'reactPlayerTiktok' */ 'peertube-video-element/react') + ) as React.LazyExoticComponent>, + }, { key: 'html', name: 'html', diff --git a/src/types.ts b/src/types.ts index 411f4f2b..f43acbf5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,6 +5,7 @@ import type YouTubeVideoElement from 'youtube-video-element'; import type VimeoVideoElement from 'vimeo-video-element'; import type TwitchVideoElement from 'twitch-video-element'; import type TikTokVideoElement from 'tiktok-video-element'; +import type PeerTubeVideoElement from 'peertube-video-element'; interface VideoHTMLAttributes extends MediaHTMLAttributes { height?: number | string | undefined; @@ -55,4 +56,5 @@ export interface Config { vimeo?: VimeoVideoElement['config']; wistia?: Record; youtube?: YouTubeVideoElement['config']; + peertube?: PeerTubeVideoElement['config']; }