livekit-client
Advanced tools
Comparing version 1.15.3 to 1.15.4
@@ -136,3 +136,7 @@ import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; | ||
*/ | ||
EXCELLENT = 2 | ||
EXCELLENT = 2, | ||
/** | ||
* @generated from enum value: LOST = 3; | ||
*/ | ||
LOST = 3 | ||
} | ||
@@ -384,2 +388,8 @@ /** | ||
canUpdateMetadata: boolean; | ||
/** | ||
* indicates that participant is an agent | ||
* | ||
* @generated from field: bool agent = 11; | ||
*/ | ||
agent: boolean; | ||
constructor(data?: PartialMessage<ParticipantPermission>); | ||
@@ -386,0 +396,0 @@ static readonly runtime: typeof proto3; |
@@ -12,2 +12,7 @@ import type TypedEmitter from 'typed-emitter'; | ||
Poor = "poor", | ||
/** | ||
* Indicates that a participant has temporarily (or permanently) lost connection to LiveKit. | ||
* For permanent disconnection a `ParticipantDisconnected` event will be emitted after a timeout | ||
*/ | ||
Lost = "lost", | ||
Unknown = "unknown" | ||
@@ -39,2 +44,3 @@ } | ||
get isEncrypted(): boolean; | ||
get isAgent(): boolean; | ||
/** @internal */ | ||
@@ -41,0 +47,0 @@ constructor(sid: string, identity: string, name?: string, metadata?: string); |
@@ -67,5 +67,2 @@ import type TypedEventEmitter from 'typed-emitter'; | ||
protected removeAppVisibilityListener(): void; | ||
private handleElementSuspended; | ||
private handleElementPlay; | ||
private debouncedPlaybackStateChange; | ||
} | ||
@@ -72,0 +69,0 @@ export declare function attachToElement(track: MediaStreamTrack, element: HTMLMediaElement): void; |
export declare const version: string; | ||
export declare const protocolVersion = 10; | ||
export declare const protocolVersion = 11; | ||
//# sourceMappingURL=version.d.ts.map |
@@ -136,3 +136,7 @@ import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; | ||
*/ | ||
EXCELLENT = 2 | ||
EXCELLENT = 2, | ||
/** | ||
* @generated from enum value: LOST = 3; | ||
*/ | ||
LOST = 3 | ||
} | ||
@@ -384,2 +388,8 @@ /** | ||
canUpdateMetadata: boolean; | ||
/** | ||
* indicates that participant is an agent | ||
* | ||
* @generated from field: bool agent = 11; | ||
*/ | ||
agent: boolean; | ||
constructor(data?: PartialMessage<ParticipantPermission>); | ||
@@ -386,0 +396,0 @@ static readonly runtime: typeof proto3; |
@@ -12,2 +12,7 @@ import type TypedEmitter from 'typed-emitter'; | ||
Poor = "poor", | ||
/** | ||
* Indicates that a participant has temporarily (or permanently) lost connection to LiveKit. | ||
* For permanent disconnection a `ParticipantDisconnected` event will be emitted after a timeout | ||
*/ | ||
Lost = "lost", | ||
Unknown = "unknown" | ||
@@ -39,2 +44,3 @@ } | ||
get isEncrypted(): boolean; | ||
get isAgent(): boolean; | ||
/** @internal */ | ||
@@ -41,0 +47,0 @@ constructor(sid: string, identity: string, name?: string, metadata?: string); |
@@ -67,5 +67,2 @@ import type TypedEventEmitter from 'typed-emitter'; | ||
protected removeAppVisibilityListener(): void; | ||
private handleElementSuspended; | ||
private handleElementPlay; | ||
private debouncedPlaybackStateChange; | ||
} | ||
@@ -72,0 +69,0 @@ export declare function attachToElement(track: MediaStreamTrack, element: HTMLMediaElement): void; |
export declare const version: string; | ||
export declare const protocolVersion = 10; | ||
export declare const protocolVersion = 11; | ||
//# sourceMappingURL=version.d.ts.map |
{ | ||
"name": "livekit-client", | ||
"version": "1.15.3", | ||
"version": "1.15.4", | ||
"description": "JavaScript/TypeScript client SDK for LiveKit", | ||
@@ -84,3 +84,3 @@ "main": "./dist/livekit-client.umd.js", | ||
"typescript": "5.3.2", | ||
"vite": "4.5.0", | ||
"vite": "4.5.1", | ||
"vitest": "^0.34.0" | ||
@@ -87,0 +87,0 @@ }, |
@@ -24,2 +24,7 @@ import { EventEmitter } from 'events'; | ||
Poor = 'poor', | ||
/** | ||
* Indicates that a participant has temporarily (or permanently) lost connection to LiveKit. | ||
* For permanent disconnection a `ParticipantDisconnected` event will be emitted after a timeout | ||
*/ | ||
Lost = 'lost', | ||
Unknown = 'unknown', | ||
@@ -36,2 +41,4 @@ } | ||
return ConnectionQuality.Poor; | ||
case ProtoQuality.LOST: | ||
return ConnectionQuality.Lost; | ||
default: | ||
@@ -82,2 +89,6 @@ return ConnectionQuality.Unknown; | ||
get isAgent() { | ||
return this.permissions?.agent ?? false; | ||
} | ||
/** @internal */ | ||
@@ -84,0 +95,0 @@ constructor(sid: string, identity: string, name?: string, metadata?: string) { |
import { EventEmitter } from 'events'; | ||
import { debounce } from 'ts-debounce'; | ||
import type TypedEventEmitter from 'typed-emitter'; | ||
import type { SignalClient } from '../../api/SignalClient'; | ||
import log from '../../logger'; | ||
import { TrackSource, TrackType } from '../../proto/livekit_models_pb'; | ||
@@ -116,5 +116,2 @@ import { StreamState as ProtoStreamState } from '../../proto/livekit_rtc_pb'; | ||
this.attachedElements.push(element); | ||
// listen to suspend events in order to detect auto playback issues | ||
element.addEventListener('suspend', this.handleElementSuspended); | ||
element.addEventListener('playing', this.handleElementPlay); | ||
} | ||
@@ -129,24 +126,35 @@ | ||
const allMediaStreamTracks = (element.srcObject as MediaStream).getTracks(); | ||
if (allMediaStreamTracks.some((tr) => tr.kind === 'audio')) { | ||
// manually play audio to detect audio playback status | ||
element | ||
.play() | ||
.then(() => { | ||
this.emit(TrackEvent.AudioPlaybackStarted); | ||
}) | ||
.catch((e) => { | ||
// If audio playback isn't allowed make sure we still play back the video | ||
if ( | ||
element && | ||
allMediaStreamTracks.some((tr) => tr.kind === 'video') && | ||
e.name === 'NotAllowedError' | ||
) { | ||
element.muted = true; | ||
element.play().catch(() => { | ||
// catch for Safari, exceeded options at this point to automatically play the media element | ||
}); | ||
} | ||
}); | ||
} | ||
const hasAudio = allMediaStreamTracks.some((tr) => tr.kind === 'audio'); | ||
// manually play media to detect auto playback status | ||
element | ||
.play() | ||
.then(() => { | ||
this.emit(hasAudio ? TrackEvent.AudioPlaybackStarted : TrackEvent.VideoPlaybackStarted); | ||
}) | ||
.catch((e) => { | ||
if (e.name === 'NotAllowedError') { | ||
this.emit(hasAudio ? TrackEvent.AudioPlaybackFailed : TrackEvent.VideoPlaybackFailed, e); | ||
} else if (e.name === 'AbortError') { | ||
// commonly triggered by another `play` request, only log for debugging purposes | ||
log.debug( | ||
`${hasAudio ? 'audio' : 'video'} playback aborted, likely due to new play request`, | ||
); | ||
} else { | ||
log.warn(`could not playback ${hasAudio ? 'audio' : 'video'}`, e); | ||
} | ||
// If audio playback isn't allowed make sure we still play back the video | ||
if ( | ||
hasAudio && | ||
element && | ||
allMediaStreamTracks.some((tr) => tr.kind === 'video') && | ||
e.name === 'NotAllowedError' | ||
) { | ||
element.muted = true; | ||
element.play().catch(() => { | ||
// catch for Safari, exceeded options at this point to automatically play the media element | ||
}); | ||
} | ||
}); | ||
this.emit(TrackEvent.ElementAttached, element); | ||
@@ -175,4 +183,2 @@ return element; | ||
this.recycleElement(element); | ||
element.removeEventListener('suspend', this.handleElementSuspended); | ||
element.removeEventListener('playing', this.handleElementPlay); | ||
this.emit(TrackEvent.ElementDetached, element); | ||
@@ -188,4 +194,2 @@ } | ||
this.recycleElement(elm); | ||
elm.removeEventListener('suspend', this.handleElementSuspended); | ||
elm.removeEventListener('playing', this.handleElementPlay); | ||
this.emit(TrackEvent.ElementDetached, elm); | ||
@@ -277,20 +281,2 @@ }); | ||
} | ||
private handleElementSuspended = () => { | ||
this.debouncedPlaybackStateChange(false); | ||
}; | ||
private handleElementPlay = () => { | ||
this.debouncedPlaybackStateChange(true); | ||
}; | ||
private debouncedPlaybackStateChange = debounce((allowed: boolean) => { | ||
// we debounce this as Safari triggers both `playing` and `suspend` shortly after one another | ||
// in order not to raise the wrong event, we debounce the call to make sure we only emit the correct status | ||
if (this.kind === Track.Kind.Audio) { | ||
this.emit(allowed ? TrackEvent.AudioPlaybackStarted : TrackEvent.AudioPlaybackFailed); | ||
} else if (this.kind === Track.Kind.Video) { | ||
this.emit(allowed ? TrackEvent.VideoPlaybackStarted : TrackEvent.VideoPlaybackFailed); | ||
} | ||
}, 300); | ||
} | ||
@@ -348,3 +334,3 @@ | ||
element.play().catch(() => { | ||
/** do nothing, we watch the `suspended` event do deal with these failures */ | ||
/** do nothing */ | ||
}); | ||
@@ -351,0 +337,0 @@ }, 0); |
import { version as v } from '../package.json'; | ||
export const version = v; | ||
export const protocolVersion = 10; | ||
export const protocolVersion = 11; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
5946466
58393