@flyfish-dev/rtsp-player 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -0
- package/dist/index.d.ts +54 -0
- package/dist/react.d.ts +29 -0
- package/dist/react.js +87 -0
- package/dist/rtsp-player.esm.js +922 -0
- package/dist/rtsp-player.global.js +247 -0
- package/dist/vue.d.ts +22 -0
- package/dist/vue.js +67 -0
- package/dist/web.js +922 -0
- package/examples/index.html +21 -0
- package/package.json +48 -0
- package/src/global.js +246 -0
- package/src/index.d.ts +54 -0
- package/src/react.d.ts +29 -0
- package/src/react.js +86 -0
- package/src/vue.d.ts +22 -0
- package/src/vue.js +66 -0
- package/src/web.js +921 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// RTSP SDK 0.1.23 - generated by scripts/build-sdk.mjs
|
|
2
|
+
(function () {
|
|
3
|
+
const DEFAULT_TAG_NAME = "rtsp-player";
|
|
4
|
+
const DEFAULT_WIDTH = "640px";
|
|
5
|
+
const DEFAULT_HEIGHT = "360px";
|
|
6
|
+
const frameOwners = new WeakMap();
|
|
7
|
+
const config = {
|
|
8
|
+
extensionId: "",
|
|
9
|
+
tagName: DEFAULT_TAG_NAME,
|
|
10
|
+
runtime: "extension",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function currentScriptExtensionId() {
|
|
14
|
+
const script = document.currentScript;
|
|
15
|
+
return script && script.dataset ? script.dataset.extensionId || "" : "";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function normalizeExtensionId(value) {
|
|
19
|
+
return String(value || "").trim().replace(/^chrome-extension:\/\//, "").replace(/\/.*$/, "");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function extensionOrigin(extensionId) {
|
|
23
|
+
const id = normalizeExtensionId(extensionId);
|
|
24
|
+
return id ? `chrome-extension://${id}` : "";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function toCssSize(value, fallback) {
|
|
28
|
+
if (value === undefined || value === null || value === "") return fallback;
|
|
29
|
+
const text = String(value);
|
|
30
|
+
return /^\d+$/.test(text) ? `${text}px` : text;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function setBooleanAttribute(el, name, enabled) {
|
|
34
|
+
if (enabled === undefined) return;
|
|
35
|
+
if (enabled) el.setAttribute(name, "");
|
|
36
|
+
else el.removeAttribute(name);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function configureRTSP(options) {
|
|
40
|
+
options = options || {};
|
|
41
|
+
if (options.extensionId !== undefined) config.extensionId = normalizeExtensionId(options.extensionId);
|
|
42
|
+
if (options.tagName) config.tagName = String(options.tagName);
|
|
43
|
+
if (options.runtime) config.runtime = String(options.runtime);
|
|
44
|
+
return Object.assign({}, config);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function updateRTSPPlayer(el, options) {
|
|
48
|
+
options = options || {};
|
|
49
|
+
const map = {
|
|
50
|
+
url: options.url,
|
|
51
|
+
src: options.src,
|
|
52
|
+
width: options.width,
|
|
53
|
+
height: options.height,
|
|
54
|
+
transport: options.transport,
|
|
55
|
+
runtime: options.runtime,
|
|
56
|
+
codec: options.codec,
|
|
57
|
+
"media-transport": options.mediaTransport,
|
|
58
|
+
"rtsp-transport": options.rtspTransport,
|
|
59
|
+
"extension-id": options.extensionId,
|
|
60
|
+
};
|
|
61
|
+
Object.keys(map).forEach((key) => {
|
|
62
|
+
const value = map[key];
|
|
63
|
+
if (value !== undefined && value !== null && value !== "") el.setAttribute(key, String(value));
|
|
64
|
+
});
|
|
65
|
+
setBooleanAttribute(el, "autoplay", options.autoplay);
|
|
66
|
+
setBooleanAttribute(el, "controls", options.controls);
|
|
67
|
+
setBooleanAttribute(el, "muted", options.muted);
|
|
68
|
+
return el;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function defineRTSPPlayer(tagName, options) {
|
|
72
|
+
configureRTSP(options);
|
|
73
|
+
const name = String(tagName || config.tagName || DEFAULT_TAG_NAME);
|
|
74
|
+
const existing = customElements.get(name);
|
|
75
|
+
if (existing) return existing;
|
|
76
|
+
|
|
77
|
+
class RTSPPlayerElement extends HTMLElement {
|
|
78
|
+
static get observedAttributes() {
|
|
79
|
+
return ["url", "src", "width", "height", "autoplay", "controls", "muted", "transport", "media-transport", "rtsp-transport", "codec", "runtime", "extension-id"];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
constructor() {
|
|
83
|
+
super();
|
|
84
|
+
this._iframe = null;
|
|
85
|
+
this._loaded = false;
|
|
86
|
+
this.attachShadow({ mode: "open" });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
connectedCallback() {
|
|
90
|
+
this._render();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
disconnectedCallback() {
|
|
94
|
+
if (this._iframe && this._iframe.contentWindow) frameOwners.delete(this._iframe.contentWindow);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
attributeChangedCallback() {
|
|
98
|
+
this._resize();
|
|
99
|
+
this._sendInit();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
play(url) {
|
|
103
|
+
if (url) this.setAttribute("url", url);
|
|
104
|
+
this._sendInit();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
stop() {
|
|
108
|
+
if (this._iframe && this._iframe.contentWindow) {
|
|
109
|
+
this._iframe.contentWindow.postMessage({ type: "RTSP_PLAYER_STOP" }, this._origin());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_extensionId() {
|
|
114
|
+
return normalizeExtensionId(
|
|
115
|
+
this.getAttribute("extension-id") ||
|
|
116
|
+
config.extensionId ||
|
|
117
|
+
window.RTSP_EXTENSION_ID ||
|
|
118
|
+
window.RTSP_WEB_PLAYER_EXTENSION_ID ||
|
|
119
|
+
currentScriptExtensionId(),
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
_origin() {
|
|
124
|
+
return extensionOrigin(this._extensionId());
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
_render() {
|
|
128
|
+
if (this._iframe || !this.shadowRoot) return;
|
|
129
|
+
this.shadowRoot.innerHTML = `
|
|
130
|
+
<style>
|
|
131
|
+
:host{display:inline-block;background:#050505;min-width:160px;min-height:90px;contain:content;}
|
|
132
|
+
.rtsp-host{width:100%;height:100%;background:#050505;position:relative;overflow:hidden;border-radius:6px;}
|
|
133
|
+
iframe{width:100%;height:100%;border:0;background:#050505;display:block;}
|
|
134
|
+
.missing{height:100%;min-height:120px;display:flex;align-items:center;justify-content:center;background:#151515;color:#ddd;font:12px system-ui,sans-serif;text-align:center;padding:12px;box-sizing:border-box;}
|
|
135
|
+
.gateway-guide{height:100%;min-height:170px;display:grid;align-content:center;gap:10px;padding:18px;background:#111312;color:#e9ede8;font:13px system-ui,sans-serif;box-sizing:border-box;}
|
|
136
|
+
.gateway-guide strong{color:#f4f5f2;font-size:15px;}
|
|
137
|
+
.gateway-guide span{color:#b6bbb4;line-height:1.5;}
|
|
138
|
+
.gateway-guide a{display:inline-flex;width:max-content;max-width:100%;align-items:center;min-height:34px;padding:0 10px;border:1px solid #435048;border-radius:6px;background:#223423;color:#ecfff0;text-decoration:none;}
|
|
139
|
+
</style>
|
|
140
|
+
<div class="rtsp-host"></div>
|
|
141
|
+
`;
|
|
142
|
+
this._resize();
|
|
143
|
+
const host = this.shadowRoot.querySelector(".rtsp-host");
|
|
144
|
+
const origin = this._origin();
|
|
145
|
+
if (!origin) {
|
|
146
|
+
host.innerHTML = gatewayGuideHTML(
|
|
147
|
+
"需要安装 RTSP Gateway",
|
|
148
|
+
"普通网页不能直接访问 rtsp://。请先安装 RTSP Gateway 与 Chrome 扩展,或在 Electron/Tauri 中使用 desktop runtime bridge。",
|
|
149
|
+
);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const iframe = document.createElement("iframe");
|
|
154
|
+
iframe.src = `${origin}/player/player.html`;
|
|
155
|
+
iframe.allow = "autoplay; fullscreen";
|
|
156
|
+
iframe.referrerPolicy = "no-referrer";
|
|
157
|
+
iframe.addEventListener("load", () => {
|
|
158
|
+
this._loaded = true;
|
|
159
|
+
frameOwners.set(iframe.contentWindow, this);
|
|
160
|
+
this._sendInit();
|
|
161
|
+
});
|
|
162
|
+
host.appendChild(iframe);
|
|
163
|
+
this._iframe = iframe;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
_resize() {
|
|
167
|
+
this.style.width = toCssSize(this.getAttribute("width") || this.style.width, DEFAULT_WIDTH);
|
|
168
|
+
this.style.height = toCssSize(this.getAttribute("height") || this.style.height, DEFAULT_HEIGHT);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
_sendInit() {
|
|
172
|
+
const origin = this._origin();
|
|
173
|
+
if (!this._loaded || !this._iframe || !this._iframe.contentWindow || !origin) return;
|
|
174
|
+
this._iframe.contentWindow.postMessage({
|
|
175
|
+
type: "RTSP_PLAYER_INIT",
|
|
176
|
+
url: this.getAttribute("url") || this.getAttribute("src") || "",
|
|
177
|
+
autoplay: this.hasAttribute("autoplay"),
|
|
178
|
+
controls: this.hasAttribute("controls"),
|
|
179
|
+
muted: this.hasAttribute("muted"),
|
|
180
|
+
transport: this.getAttribute("rtsp-transport") || (this.getAttribute("transport") === "tcp" ? "tcp" : "tcp"),
|
|
181
|
+
rtspTransport: this.getAttribute("rtsp-transport") || "tcp",
|
|
182
|
+
mediaTransport: this.getAttribute("media-transport") || this.getAttribute("transport") || "auto",
|
|
183
|
+
codec: this.getAttribute("codec") || "auto",
|
|
184
|
+
}, origin);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
customElements.define(name, RTSPPlayerElement);
|
|
189
|
+
return RTSPPlayerElement;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function createRTSPPlayer(options) {
|
|
193
|
+
options = options || {};
|
|
194
|
+
const tagName = options.tagName || config.tagName || DEFAULT_TAG_NAME;
|
|
195
|
+
defineRTSPPlayer(tagName, options);
|
|
196
|
+
const el = document.createElement(tagName);
|
|
197
|
+
updateRTSPPlayer(el, options);
|
|
198
|
+
return el;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function gatewayGuideHTML(title, body) {
|
|
202
|
+
return `
|
|
203
|
+
<div class="gateway-guide">
|
|
204
|
+
<strong>${escapeHTML(title)}</strong>
|
|
205
|
+
<span>${escapeHTML(body)}</span>
|
|
206
|
+
<a href="https://rtsp.flyfish.dev/#docs/web-component-gateway.md" target="_blank" rel="noreferrer">查看 Gateway 安装指引</a>
|
|
207
|
+
</div>
|
|
208
|
+
`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function escapeHTML(value) {
|
|
212
|
+
return String(value).replace(/[&<>"']/g, (ch) => ({
|
|
213
|
+
"&": "&",
|
|
214
|
+
"<": "<",
|
|
215
|
+
">": ">",
|
|
216
|
+
"\"": """,
|
|
217
|
+
"'": "'",
|
|
218
|
+
}[ch]));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!window.__RTSP_PLAYER_MESSAGE_BRIDGE__) {
|
|
222
|
+
window.__RTSP_PLAYER_MESSAGE_BRIDGE__ = true;
|
|
223
|
+
window.addEventListener("message", (event) => {
|
|
224
|
+
const el = event.source ? frameOwners.get(event.source) : null;
|
|
225
|
+
if (!el || !event.data || !event.data.type || !event.data.type.startsWith("RTSP_PLAYER_")) return;
|
|
226
|
+
if (event.origin !== el._origin()) return;
|
|
227
|
+
const type = event.data.type.replace(/^RTSP_PLAYER_/, "").toLowerCase();
|
|
228
|
+
el.dispatchEvent(new CustomEvent(type, {
|
|
229
|
+
detail: event.data,
|
|
230
|
+
bubbles: true,
|
|
231
|
+
composed: true,
|
|
232
|
+
}));
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const id = window.RTSP_EXTENSION_ID || window.RTSP_WEB_PLAYER_EXTENSION_ID || currentScriptExtensionId();
|
|
237
|
+
if (id) configureRTSP({ extensionId: id });
|
|
238
|
+
defineRTSPPlayer(DEFAULT_TAG_NAME);
|
|
239
|
+
|
|
240
|
+
window.RTSP = Object.assign(window.RTSP || {}, {
|
|
241
|
+
version: "0.1.23",
|
|
242
|
+
configure: configureRTSP,
|
|
243
|
+
definePlayer: defineRTSPPlayer,
|
|
244
|
+
createPlayer: createRTSPPlayer,
|
|
245
|
+
updatePlayer: updateRTSPPlayer,
|
|
246
|
+
});
|
|
247
|
+
})();
|
package/dist/vue.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DefineComponent } from "vue";
|
|
2
|
+
|
|
3
|
+
export interface RtspPlayerProps {
|
|
4
|
+
extensionId?: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
src?: string;
|
|
7
|
+
width?: string | number;
|
|
8
|
+
height?: string | number;
|
|
9
|
+
autoplay?: boolean;
|
|
10
|
+
controls?: boolean;
|
|
11
|
+
muted?: boolean;
|
|
12
|
+
transport?: "auto" | "webrtc" | "ws-annexb" | "tcp" | string;
|
|
13
|
+
rtspTransport?: "tcp" | "udp" | string;
|
|
14
|
+
mediaTransport?: "auto" | "webrtc" | "ws-annexb" | string;
|
|
15
|
+
codec?: "auto" | "h264" | "h265" | string;
|
|
16
|
+
runtime?: "extension" | "desktop" | "auto";
|
|
17
|
+
tagName?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export declare const RtspPlayer: DefineComponent<RtspPlayerProps>;
|
|
21
|
+
|
|
22
|
+
export default RtspPlayer;
|
package/dist/vue.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// RTSP SDK 0.1.23 - generated by scripts/build-sdk.mjs
|
|
2
|
+
import {
|
|
3
|
+
defineComponent,
|
|
4
|
+
h,
|
|
5
|
+
onBeforeUnmount,
|
|
6
|
+
onMounted,
|
|
7
|
+
ref,
|
|
8
|
+
watch,
|
|
9
|
+
} from "vue";
|
|
10
|
+
import { configureRTSP, defineRTSPPlayer, updateRTSPPlayer } from "./web.js";
|
|
11
|
+
|
|
12
|
+
export const RtspPlayer = defineComponent({
|
|
13
|
+
name: "RtspPlayer",
|
|
14
|
+
props: {
|
|
15
|
+
extensionId: String,
|
|
16
|
+
url: String,
|
|
17
|
+
src: String,
|
|
18
|
+
width: { type: [String, Number], default: 640 },
|
|
19
|
+
height: { type: [String, Number], default: 360 },
|
|
20
|
+
autoplay: { type: Boolean, default: false },
|
|
21
|
+
controls: { type: Boolean, default: true },
|
|
22
|
+
muted: { type: Boolean, default: false },
|
|
23
|
+
transport: { type: String, default: "auto" },
|
|
24
|
+
rtspTransport: { type: String, default: "tcp" },
|
|
25
|
+
mediaTransport: String,
|
|
26
|
+
codec: { type: String, default: "auto" },
|
|
27
|
+
runtime: { type: String, default: "extension" },
|
|
28
|
+
tagName: { type: String, default: "rtsp-player" },
|
|
29
|
+
},
|
|
30
|
+
emits: ["ready", "error", "starting"],
|
|
31
|
+
setup(props, { emit, attrs }) {
|
|
32
|
+
const el = ref(null);
|
|
33
|
+
|
|
34
|
+
const sync = () => {
|
|
35
|
+
if (!el.value) return;
|
|
36
|
+
configureRTSP({ extensionId: props.extensionId, tagName: props.tagName, runtime: props.runtime });
|
|
37
|
+
defineRTSPPlayer(props.tagName);
|
|
38
|
+
updateRTSPPlayer(el.value, props);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const onReady = (event) => emit("ready", event);
|
|
42
|
+
const onError = (event) => emit("error", event);
|
|
43
|
+
const onStarting = (event) => emit("starting", event);
|
|
44
|
+
|
|
45
|
+
onMounted(() => {
|
|
46
|
+
sync();
|
|
47
|
+
el.value?.addEventListener("ready", onReady);
|
|
48
|
+
el.value?.addEventListener("error", onError);
|
|
49
|
+
el.value?.addEventListener("starting", onStarting);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
onBeforeUnmount(() => {
|
|
53
|
+
el.value?.removeEventListener("ready", onReady);
|
|
54
|
+
el.value?.removeEventListener("error", onError);
|
|
55
|
+
el.value?.removeEventListener("starting", onStarting);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
watch(() => ({ ...props }), sync, { deep: true });
|
|
59
|
+
|
|
60
|
+
return () => h(props.tagName, {
|
|
61
|
+
...attrs,
|
|
62
|
+
ref: el,
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export default RtspPlayer;
|