diff --git a/CHANGES.md b/CHANGES.md index 30fd6c84..b96a545e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,9 @@ ## develop +- [CHANGE] シグナリングオプションの `multistream` は false の時のみレガシーストリームを使用する + - レガシーストリームを使用したい場合は `multistream: false` の指定が必須となる + - @tnamao - [CHANGE] stopAudioTrack と stopVideoTrack を非推奨にする - 代わりに名前を変えただけの removeAudioTrack と removeVideoTrack を用意する - @voluntas diff --git a/examples/check.html b/examples/check.html index 7ececf39..716ce47e 100644 --- a/examples/check.html +++ b/examples/check.html @@ -21,7 +21,7 @@

リリース前の動作確認用サンプル

※ クエリストリングの signalingUrl パラメータでも指定可能
-

チャネル ID: sora-js-sdk:check:singlestream

+

チャネル ID: sora-js-sdk:check:legacystream

要確認ブラウザ: - - + +

sendonly, Opus

-
+

recvonly

-
+

チャネル ID: sora-js-sdk:check:multistream

@@ -183,23 +183,23 @@

multistream, E2EE, recvonly

document.querySelectorAll('.multistream').forEach(x => x.innerHTML = null); } - let singlestreamCheckConnections = []; - async function startSinglestreamCheck() { - stopSinglestreamCheck(); + let legacystreamCheckConnections = []; + async function startLegacystreamCheck() { + stopLegacystreamCheck(); - const channelId = 'sora-js-sdk:check:singlestream'; - singlestreamCheckConnections = [ - await connect(channelId, 'singlestream-sendonly-videos', 'sendonly', + const channelId = 'sora-js-sdk:check:legacystream'; + legacystreamCheckConnections = [ + await connect(channelId, 'legacystream-sendonly-videos', 'sendonly', {multistream: false}), - await connect(channelId, 'singlestream-recvonly-videos', 'recvonly', + await connect(channelId, 'legacystream-recvonly-videos', 'recvonly', {multistream: false}), ]; } - async function stopSinglestreamCheck() { - singlestreamCheckConnections.forEach(x => x.disconnect()); - singlestreamCheckConnections = []; - document.querySelectorAll('.singlestream').forEach(x => x.innerHTML = null); + async function stopLegacystreamCheck() { + legacystreamCheckConnections.forEach(x => x.disconnect()); + legacystreamCheckConnections = []; + document.querySelectorAll('.legacystream').forEach(x => x.innerHTML = null); } function initLyra() { diff --git a/packages/sdk/src/publisher.ts b/packages/sdk/src/publisher.ts index a81a204b..7333ef3d 100644 --- a/packages/sdk/src/publisher.ts +++ b/packages/sdk/src/publisher.ts @@ -19,9 +19,10 @@ export default class ConnectionPublisher extends ConnectionBase { * @public */ async connect(stream: MediaStream): Promise { - if (this.options.multistream) { + // options.multistream が明示的に false を指定した時だけレガシーストリームにする + if (this.options.multistream === false) { await Promise.race([ - this.multiStream(stream).finally(() => { + this.legacyStream(stream).finally(() => { this.clearConnectionTimeout() this.clearMonitorSignalingWebSocketEvent() }), @@ -30,7 +31,7 @@ export default class ConnectionPublisher extends ConnectionBase { ]) } else { await Promise.race([ - this.singleStream(stream).finally(() => { + this.multiStream(stream).finally(() => { this.clearConnectionTimeout() this.clearMonitorSignalingWebSocketEvent() }), @@ -44,11 +45,11 @@ export default class ConnectionPublisher extends ConnectionBase { } /** - * シングルストリームで Sora へ接続するメソッド + * レガシーストリームで Sora へ接続するメソッド * * @param stream - メディアストリーム */ - private async singleStream(stream: MediaStream): Promise { + private async legacyStream(stream: MediaStream): Promise { await this.disconnect() this.setupE2EE() const ws = await this.getSignalingWebSocket(this.signalingUrlCandidates) diff --git a/packages/sdk/src/sora.ts b/packages/sdk/src/sora.ts index 68b902b4..499ab0ea 100644 --- a/packages/sdk/src/sora.ts +++ b/packages/sdk/src/sora.ts @@ -82,14 +82,12 @@ class SoraConnection { metadata: JSONType = null, options: ConnectionOptions = { audio: true, video: true }, ): ConnectionPublisher { - // sendrecv の場合、multistream に初期値を指定する - const sendrecvOptions: ConnectionOptions = Object.assign({ multistream: true }, options) return new ConnectionPublisher( this.signalingUrlCandidates, 'sendrecv', channelId, metadata, - sendrecvOptions, + options, this.debug, ) } diff --git a/packages/sdk/src/subscriber.ts b/packages/sdk/src/subscriber.ts index f1dfaf7e..68b21f44 100644 --- a/packages/sdk/src/subscriber.ts +++ b/packages/sdk/src/subscriber.ts @@ -17,9 +17,10 @@ export default class ConnectionSubscriber extends ConnectionBase { */ // biome-ignore lint/suspicious/noConfusingVoidType: stream が なのでどうしようもない async connect(): Promise { - if (this.options.multistream) { - await Promise.race([ - this.multiStream().finally(() => { + // options.multistream が明示的に false を指定した時だけレガシーストリームにする + if (this.options.multistream === false) { + const stream = await Promise.race([ + this.legacyStream().finally(() => { this.clearConnectionTimeout() this.clearMonitorSignalingWebSocketEvent() }), @@ -28,10 +29,10 @@ export default class ConnectionSubscriber extends ConnectionBase { ]) this.monitorWebSocketEvent() this.monitorPeerConnectionState() - return + return stream } - const stream = await Promise.race([ - this.singleStream().finally(() => { + await Promise.race([ + this.multiStream().finally(() => { this.clearConnectionTimeout() this.clearMonitorSignalingWebSocketEvent() }), @@ -40,13 +41,12 @@ export default class ConnectionSubscriber extends ConnectionBase { ]) this.monitorWebSocketEvent() this.monitorPeerConnectionState() - return stream } /** - * シングルストリームで Sora へ接続するメソッド + * レガシーストリームで Sora へ接続するメソッド */ - private async singleStream(): Promise { + private async legacyStream(): Promise { await this.disconnect() this.setupE2EE() const ws = await this.getSignalingWebSocket(this.signalingUrlCandidates) diff --git a/packages/sdk/src/utils.ts b/packages/sdk/src/utils.ts index 7809ab03..7b70aa4a 100644 --- a/packages/sdk/src/utils.ts +++ b/packages/sdk/src/utils.ts @@ -146,7 +146,8 @@ export function createSignalingMessage( video: true, } // role: sendrecv で multistream: false の場合は例外を発生させる - if (role === 'sendrecv' && options.multistream !== true) { + // options.multistream === undefined は multistream として扱う + if (role === 'sendrecv' && options.multistream === false) { throw new Error( "Failed to parse options. Options multistream must be true when connecting using 'sendrecv'", ) diff --git a/packages/sdk/tests/utils.test.ts b/packages/sdk/tests/utils.test.ts index cd7a4772..34352ef9 100644 --- a/packages/sdk/tests/utils.test.ts +++ b/packages/sdk/tests/utils.test.ts @@ -1,6 +1,6 @@ -import { test, expect } from 'vitest' -import { createSignalingMessage } from '../src/utils' +import { expect, test } from 'vitest' import { type AudioCodecType, DataChannelDirection, VideoCodecType } from '../src/types' +import { createSignalingMessage } from '../src/utils' const channelId = '7N3fsMHob' const metadata = 'PG9A6RXgYqiqWKOVO' @@ -47,6 +47,15 @@ test('createSignalingMessage simple sendrecv', () => { ).toEqual(expectedMessage) }) +test('createSignalingMessage sendrecv and undefined multistream', () => { + const expectedMessage = Object.assign({}, baseExpectedMessage, { + role: 'sendrecv', + }) + expect(createSignalingMessage(sdp, 'sendrecv', channelId, undefined, {}, false)).toEqual( + expectedMessage, + ) +}) + test('createSignalingMessage invalid role', () => { expect(() => { createSignalingMessage(sdp, 'test', channelId, metadata, {}, false) @@ -55,7 +64,7 @@ test('createSignalingMessage invalid role', () => { test('createSignalingMessage sendrecv and multistream: false', () => { expect(() => { - createSignalingMessage(sdp, 'sendrecv', channelId, metadata, {}, false) + createSignalingMessage(sdp, 'sendrecv', channelId, metadata, { multistream: false }, false) }).toThrow( Error( "Failed to parse options. Options multistream must be true when connecting using 'sendrecv'", @@ -140,6 +149,14 @@ test('createSignalingMessage multistream: true', () => { ) }) +test('createSignalingMessage undefined multistream', () => { + const options = {} + const expectedMessage = Object.assign({}, baseExpectedMessage, {}) + expect(createSignalingMessage(sdp, 'sendonly', channelId, undefined, options, false)).toEqual( + expectedMessage, + ) +}) + test('createSignalingMessage multistream: false', () => { const options = { multistream: false } const expectedMessage = Object.assign({}, baseExpectedMessage, {