avcon-sdk-srs
Version:
Avcon SRS SDK
239 lines (238 loc) • 8.79 kB
JavaScript
var g = Object.defineProperty;
var P = (t, e, i) => e in t ? g(t, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : t[e] = i;
var a = (t, e, i) => P(t, typeof e != "symbol" ? e + "" : e, i);
const k = { code: -1, message: "Invalid JSON response" };
function m(t) {
if (!t.ok)
throw t;
return t.json().then((e) => {
if (e.code)
throw e;
return e;
});
}
function f(t, e) {
return fetch(t.apiUrl, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
api: t.apiUrl,
tid: t.tid,
streamurl: t.streamUrl,
sdp: e.sdp,
clientip: null
})
}).then(m).catch((i) => {
if (i instanceof SyntaxError)
return k;
throw i;
});
}
function w(t, e) {
const { schema: i, httpApiPort: r, httpsApiPort: o } = h.getConfig(), n = new URL(t.replace(/^(rtmp|webrtc|rtc)/, i)), c = n.port || n.protocol === "https" ? o : r, T = e.endsWith("/") ? e : e + "/";
return {
apiUrl: `${n.protocol}//${n.hostname}:${c}${T}`,
streamUrl: t,
tid: ((/* @__PURE__ */ new Date()).getTime() * Math.random() * 100).toString(16).slice(0, 7)
};
}
class d extends Error {
constructor(e, i) {
super(), this.name = e, this.message = i, this.stack = new Error().stack;
}
}
var C = /* @__PURE__ */ ((t) => (t.Normal = "normal", t.Screen = "screen", t))(C || {});
async function l(t = { audio: !0, video: !0 }, e = "normal") {
if (!navigator.mediaDevices && window.location.protocol === "http:" && window.location.hostname !== "localhost")
throw new d(
"HttpsRequiredError",
"Please use HTTPS or localhost to publish, read https://github.com/ossrs/srs/issues/2762#issuecomment-983147576"
);
const i = e === "normal" ? await navigator.mediaDevices.getUserMedia(t) : await navigator.mediaDevices.getDisplayMedia(t), r = i.getAudioTracks()[0], o = i.getVideoTracks()[0];
return {
audioTrack: r,
videoTrack: o,
stream: i
};
}
var s = /* @__PURE__ */ ((t) => (t[t.Pendding = 1] = "Pendding", t[t.Connecting = 2] = "Connecting", t[t.Connected = 3] = "Connected", t[t.Disconnected = 4] = "Disconnected", t))(s || {});
class u {
constructor(e) {
a(this, "constraints");
a(this, "status", s.Pendding);
a(this, "RTCPeerConnection", new RTCPeerConnection());
a(this, "stream", new MediaStream());
a(this, "audioSender", null);
a(this, "videoSender", null);
this.constraints = e || {
audio: !0,
video: !0
};
}
init() {
this.status = s.Pendding, this.stream = new MediaStream(), this.RTCPeerConnection = new RTCPeerConnection(), this.audioSender = null, this.videoSender = null;
}
close() {
this.status = s.Disconnected, this.stream.getTracks().forEach((e) => e.stop()), this.RTCPeerConnection && this.RTCPeerConnection.close(), this.RTCPeerConnection = null, this.audioSender = null, this.videoSender = null;
}
setConstraints(e) {
this.constraints = e;
}
async getWebRTCStats(e) {
if (this.RTCPeerConnection)
try {
return await this.RTCPeerConnection.getStats(e);
} catch (i) {
console.error("获取WebRTC数据统计失败:", i);
}
}
getConstraints() {
return this.constraints;
}
getStatus() {
return this.status;
}
setVideoContentHind(e, i) {
return "contentHint" in e ? (e.contentHint = i, e.contentHint !== i ? (console.warn("设置contentHint失败", i), !1) : !0) : (console.warn("浏览器不支持contentHint,不设置contentHint"), !1);
}
async setRTCDescription(e, i) {
if (this.RTCPeerConnection) {
this.status = s.Connecting;
const r = await this.RTCPeerConnection.createOffer();
await this.RTCPeerConnection.setLocalDescription(r);
const o = w(e, i);
try {
const n = await f(o, r);
return await this.RTCPeerConnection.setRemoteDescription({ type: "answer", sdp: n.sdp }), this.status = s.Connected, n;
} catch {
throw new d(
"Avcon SRS Sdk Publish Error",
"信令获取失败"
);
}
}
}
}
class v extends u {
constructor(e) {
super(e);
}
async publish(e, i, r = "detail") {
if (!(this.status === s.Pendding || this.status === s.Disconnected))
throw new d(
"Avcon SRS Sdk Error",
"当前SrsPublisher实例处于连接状态,请先调用close()方法关闭连接,再重新调用publish()方法"
);
i && this.setConstraints(i), this.RTCPeerConnection || this.init();
const { stream: o, audioTrack: n, videoTrack: c } = await l(this.constraints);
return c && (this.RTCPeerConnection.addTransceiver("video", { direction: "sendonly" }), this.setVideoContentHind(c, r), this.stream.addTrack(c), this.videoSender = this.RTCPeerConnection.addTrack(c, this.stream)), n && (this.RTCPeerConnection.addTransceiver("audio", { direction: "sendonly" }), this.stream.addTrack(n), this.audioSender = this.RTCPeerConnection.addTrack(n, this.stream)), await this.setRTCDescription(e, h.getConfig().publishApi), o;
}
closeAudio() {
this.stream.getAudioTracks()[0] && (this.stream.getAudioTracks()[0].enabled = !1);
}
closeVideo() {
this.stream.getVideoTracks()[0] && (this.stream.getVideoTracks()[0].enabled = !1);
}
openAudio() {
this.stream.getAudioTracks()[0] && (this.stream.getAudioTracks()[0].enabled = !0);
}
openVideo() {
this.stream.getVideoTracks()[0] && (this.stream.getVideoTracks()[0].enabled = !0);
}
async changeAudioTrack(e) {
const i = this.stream.getAudioTracks()[0];
i && (i.stop(), this.stream.removeTrack(i)), this.stream.addTrack(e), this.audioSender && await this.audioSender.replaceTrack(e);
}
async changeVideoTrack(e) {
const i = this.stream.getVideoTracks()[0];
i && (i.stop(), this.stream.removeTrack(i)), this.stream.addTrack(e), this.videoSender && await this.videoSender.replaceTrack(e);
}
async rePublishVideo() {
const { videoTrack: e } = await l(this.constraints);
this.changeVideoTrack(e);
}
}
class S extends u {
constructor(e = {
video: {
displaySurface: "browser"
},
audio: {
// @ts-ignore
// https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSettings/suppressLocalAudioPlayback
suppressLocalAudioPlayback: !1
// 是否 禁止本地音频播放
},
preferCurrentTab: !1
// 是否 首选(且只能选)当前页签
}) {
super(e);
}
async publish(e, i) {
if (!(this.status === s.Pendding || this.status === s.Disconnected))
throw new d(
"Avcon SRS Sdk Error",
"当前SrsPublisher实例处于连接状态,请先调用close()方法关闭连接,再重新调用publish()方法"
);
i && this.setConstraints(i), this.RTCPeerConnection || this.init(), this.RTCPeerConnection.addTransceiver("audio", { direction: "sendonly" }), this.RTCPeerConnection.addTransceiver("video", { direction: "sendonly" });
const { videoTrack: r, stream: o, audioTrack: n } = await l(this.constraints, C.Screen);
return this.stream = o, this.RTCPeerConnection.addTrack(r), n && this.RTCPeerConnection.addTrack(n), await this.setRTCDescription(e, h.getConfig().publishApi), o;
}
}
class y extends u {
constructor() {
super(), this.RTCPeerConnection.ontrack = (e) => {
this.stream.addTrack(e.track);
};
}
async play(e) {
if (!(this.status === s.Pendding || this.status === s.Disconnected))
throw new d(
"Avcon SRS Sdk Error",
"当前SrsPlayer实例处于连接状态,请先调用close()方法关闭连接,再重新调用play()方法"
);
return this.RTCPeerConnection || (this.init(), this.RTCPeerConnection.ontrack = (i) => {
this.stream.addTrack(i.track);
}), this.status = s.Connecting, this.RTCPeerConnection.addTransceiver("audio", { direction: "recvonly" }), this.RTCPeerConnection.addTransceiver("video", { direction: "recvonly" }), await this.setRTCDescription(e, h.getConfig().playApi);
}
}
const p = {
schema: "https",
httpApiPort: 1985,
httpsApiPort: 1990,
publishApi: "/rtc/v1/publish/",
playApi: "/rtc/v1/play/"
};
var R = /* @__PURE__ */ ((t) => (t[t.Pendding = 1] = "Pendding", t[t.Connecting = 2] = "Connecting", t[t.Connected = 3] = "Connected", t[t.Disconnected = 4] = "Disconnected", t))(R || {});
class b {
constructor(e) {
a(this, "sdkConfig");
this.sdkConfig = e;
}
setConfig(e) {
this.sdkConfig = {
...p,
...e
};
}
getConfig() {
return this.sdkConfig;
}
createPublisher(e) {
return new v(e);
}
createScreenPublisher(e) {
return new S(e);
}
createPlayer() {
return new y();
}
}
const h = new b(p);
export {
b as AcvconSrsSdk,
R as RTCInstanceStatus,
h as default
};