use new loadStream method

This commit is contained in:
SrGooglo 2023-04-10 16:22:31 +00:00
parent 924195c107
commit dba6e0f222
2 changed files with 97 additions and 66 deletions

View File

@ -23,14 +23,12 @@ export default class StreamViewer extends React.Component {
loading: true, loading: true,
cinemaMode: false, cinemaMode: false,
streamSources: null, stream: null,
streamInfo: null,
spectators: 0, spectators: 0,
player: null, player: null,
decoderInstance: null, decoderInstance: null,
plyrOptions: {},
} }
videoPlayerRef = React.createRef() videoPlayerRef = React.createRef()
@ -60,9 +58,12 @@ export default class StreamViewer extends React.Component {
decoderInstance.on(mpegts.Events.ERROR, this.onSourceEnd) decoderInstance.on(mpegts.Events.ERROR, this.onSourceEnd)
decoderInstance.attachMediaElement(this.videoPlayerRef.current) decoderInstance.attachMediaElement(this.videoPlayerRef.current)
decoderInstance.load() decoderInstance.load()
await decoderInstance.play() await decoderInstance.play().catch((error) => {
console.error(error)
})
this.toggleLoading(false) this.toggleLoading(false)
@ -125,54 +126,42 @@ export default class StreamViewer extends React.Component {
}) })
} }
loadStreamInfo = async (username) => { loadStream = async (payload) => {
const streamInfo = await Livestream.getStreamInfo({ username }).catch((error) => { const stream = await Livestream.getLivestream({
username: payload.username,
profile_id: payload.profile,
}).catch((error) => {
console.error(error) console.error(error)
return null return null
}) })
if (!streamInfo) { if (!stream) {
return false return false
} }
console.log("Stream info", streamInfo) console.log("Stream data >", stream)
this.setState({ this.setState({
streamInfo: streamInfo, stream: stream,
}) spectators: stream.connectedClients,
}
loadStreamSources = async (username) => {
const streamSources = await Livestream.getLivestream({ username }).catch((error) => {
console.error(error)
this.onSourceEnd(error)
return null
}) })
if (!streamSources) { return stream
return false
}
console.log("Stream sources", streamSources)
this.setState({
streamSources: streamSources,
spectators: streamSources.connectedClients,
})
} }
attachPlayer = () => { attachPlayer = () => {
// check if user has interacted with the page
const player = new Plyr("#player", { const player = new Plyr("#player", {
clickToPlay: false, clickToPlay: false,
autoplay: true, autoplay: true,
muted: true,
controls: ["mute", "volume", "fullscreen", "airplay", "options", "settings",], controls: ["mute", "volume", "fullscreen", "airplay", "options", "settings",],
settings: ["quality"], settings: ["quality"],
...this.state.plyrOptions,
}) })
player.muted = true
// insert a button to enter to cinema mode // insert a button to enter to cinema mode
player.elements.buttons.fullscreen.insertAdjacentHTML("beforeBegin", ` player.elements.buttons.fullscreen.insertAdjacentHTML("beforeBegin", `
<button class="plyr__controls__item plyr__control" type="button" data-plyr="cinema"> <button class="plyr__controls__item plyr__control" type="button" data-plyr="cinema">
@ -202,6 +191,7 @@ export default class StreamViewer extends React.Component {
this.enterPlayerAnimation() this.enterPlayerAnimation()
const requestedUsername = this.props.params.key const requestedUsername = this.props.params.key
const profile = this.props.query.profile
await this.setState({ await this.setState({
requestedUsername, requestedUsername,
@ -210,28 +200,45 @@ export default class StreamViewer extends React.Component {
this.attachPlayer() this.attachPlayer()
// get stream info // get stream info
this.loadStreamInfo(requestedUsername) const stream = await this.loadStream({
await this.loadStreamSources(requestedUsername) username: requestedUsername,
profile: profile,
})
if (this.state.streamSources) { if (!stream) {
if (!this.state.streamSources.sources) { return this.onSourceEnd()
console.error("Stream sources is not defined") }
return false // load the flv decoder (by default)
if (this.state.stream) {
if (!this.state.stream.sources) {
console.error("Stream sources not found")
return
} }
await this.loadDecoder("flv", this.state.streamSources.sources.flv) await this.loadDecoder("flv", this.state.stream.sources.flv)
} }
// TODO: Watch ws to get livestream:started event and load the decoder if it's not loaded // TODO: Watch ws to get livestream:started event and load the decoder if it's not loaded
// set a interval to update the stream info // set a interval to update the stream info
this.streamInfoInterval = setInterval(() => { this.streamInfoInterval = setInterval(() => {
this.loadStreamSources(requestedUsername) this.loadStream({
username: this.state.requestedUsername,
profile: profile,
})
}, 1000 * 60) }, 1000 * 60)
} }
componentWillUnmount = () => { componentWillUnmount = () => {
if (this.state.player) {
this.state.player.destroy()
}
if (typeof this.state.decoderInstance?.unload === "function") {
this.state.decoderInstance.unload()
}
this.exitPlayerAnimation() this.exitPlayerAnimation()
if (this.streamInfoInterval) { if (this.streamInfoInterval) {
@ -312,14 +319,14 @@ export default class StreamViewer extends React.Component {
} }
if (to) { if (to) {
app.cores.player.start({ app.cores.player.start({
src: this.state.streamSources.sources.aac, src: this.state.stream?.sources.aac,
title: this.state.streamInfo.title, title: this.state.stream?.info.title,
artist: this.state.streamInfo.username, artist: this.state.stream?.info.username,
}) })
// setLocation to main page // setLocation to main page
app.navigation.goMain() app.navigation.goMain()
} }
} }
@ -335,32 +342,34 @@ export default class StreamViewer extends React.Component {
<div className="livestream_player"> <div className="livestream_player">
<div className="livestream_player_header"> <div className="livestream_player_header">
{ {
this.state.streamInfo this.state.stream
? <> ? <>
<div className="livestream_player_header_user"> <div className="livestream_player_header_user">
<UserPreview username={this.state.requestedUsername} /> <UserPreview user={this.state.stream.user} />
{ <div className="livestream_player_indicators">
!this.state.isEnded && <div className="livestream_player_header_user_spectators"> {
<antd.Tag !this.state.isEnded && <div className="livestream_player_header_user_spectators">
icon={<Icons.Eye />} <antd.Tag
> icon={<Icons.Eye />}
{this.state.spectators} >
</antd.Tag> {this.state.spectators}
</div> </antd.Tag>
} </div>
}
</div>
</div> </div>
<div className="livestream_player_header_info"> <div className="livestream_player_header_info">
<div className="livestream_player_header_info_title"> <div className="livestream_player_header_info_title">
<h1>{this.state.streamInfo?.title}</h1> <h1>{this.state.stream.info.title}</h1>
</div> </div>
<div className="livestream_player_header_info_description"> <div className="livestream_player_header_info_description">
<Ticker <Ticker
mode="smooth" mode="smooth"
> >
{({ index }) => { {({ index }) => {
return <h4>{this.state.streamInfo?.description}</h4> return <h4>{this.state.stream.info.description}</h4>
}} }}
</Ticker> </Ticker>
</div> </div>
@ -406,7 +415,7 @@ export default class StreamViewer extends React.Component {
</div> </div>
} }
<LiveChat <LiveChat
roomId={`livestream:${this.state.requestedUsername}`} roomId={`livestream:${this.state.requestedUsername}:${this.props.query.profile ?? "default"}`}
floatingMode={this.state.cinemaMode} floatingMode={this.state.cinemaMode}
/> />
</div> </div>

View File

@ -169,14 +169,36 @@
margin-right: 20px; margin-right: 20px;
.livestream_player_header_user_spectators { .livestream_player_indicators {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 10px;
margin-top: 10px; margin-top: 10px;
.ant-tag { .livestream_player_header_user_spectators {
background-color: #eb0400; height: fit-content;
border-color: #eb0400;
color: var(--background-color-contrast); .ant-tag {
font-size: 1rem; background-color: #eb0400;
border-color: #eb0400;
color: var(--background-color-contrast);
font-size: 1rem;
}
}
.livestream_player_header_user_quality {
font-size: 1.8rem;
height: fit-content;
svg {
color: var(--text-color);
margin: 0;
}
} }
} }
} }