various fixes
This commit is contained in:
parent
05b44fc4ab
commit
60c317dedf
5 changed files with 45 additions and 18 deletions
|
@ -307,7 +307,7 @@ const VideoJsEvents = ({
|
||||||
});
|
});
|
||||||
// player.on('ended', onEnded);
|
// player.on('ended', onEnded);
|
||||||
|
|
||||||
if (isLivestreamClaim) {
|
if (isLivestreamClaim && player) {
|
||||||
player.liveTracker.on('liveedgechange', async () => {
|
player.liveTracker.on('liveedgechange', async () => {
|
||||||
// Only respond to when we fall behind
|
// Only respond to when we fall behind
|
||||||
if (player.liveTracker.atLiveEdge()) return;
|
if (player.liveTracker.atLiveEdge()) return;
|
||||||
|
|
|
@ -207,12 +207,12 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
controls: true,
|
controls: true,
|
||||||
html5: {
|
html5: {
|
||||||
hls: {
|
vhs: {
|
||||||
overrideNative: !videojs.browser.IS_ANY_SAFARI,
|
overrideNative: !videojs.browser.IS_ANY_SAFARI,
|
||||||
allowSeeksWithinUnsafeLiveWindow: true,
|
allowSeeksWithinUnsafeLiveWindow: true,
|
||||||
enableLowInitialPlaylist: false,
|
enableLowInitialPlaylist: false,
|
||||||
handlePartialData: true,
|
handlePartialData: true,
|
||||||
smoothQualityChange: true,
|
fastQualityChange: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
liveTracker: {
|
liveTracker: {
|
||||||
|
|
|
@ -15,7 +15,8 @@ export const LIVESTREAM_KILL = 'https://api.stream.odysee.com/stream/kill';
|
||||||
|
|
||||||
export const MAX_LIVESTREAM_COMMENTS = 50;
|
export const MAX_LIVESTREAM_COMMENTS = 50;
|
||||||
|
|
||||||
export const LIVESTREAM_STATUS_CHECK_INTERVAL = 30 * 1000;
|
export const LIVESTREAM_STATUS_CHECK_INTERVAL = 45 * 1000;
|
||||||
|
export const LIVESTREAM_STATUS_CHECK_INTERVAL_SOON = 15 * 1000;
|
||||||
export const LIVESTREAM_STARTS_SOON_BUFFER = 15;
|
export const LIVESTREAM_STARTS_SOON_BUFFER = 15;
|
||||||
export const LIVESTREAM_STARTED_RECENTLY_BUFFER = 15;
|
export const LIVESTREAM_STARTED_RECENTLY_BUFFER = 15;
|
||||||
export const LIVESTREAM_UPCOMING_BUFFER = 35;
|
export const LIVESTREAM_UPCOMING_BUFFER = 35;
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { formatLbryChannelName } from 'util/url';
|
||||||
import { lazyImport } from 'util/lazyImport';
|
import { lazyImport } from 'util/lazyImport';
|
||||||
import {
|
import {
|
||||||
LIVESTREAM_STATUS_CHECK_INTERVAL,
|
LIVESTREAM_STATUS_CHECK_INTERVAL,
|
||||||
|
LIVESTREAM_STATUS_CHECK_INTERVAL_SOON,
|
||||||
LIVESTREAM_STARTS_SOON_BUFFER,
|
LIVESTREAM_STARTS_SOON_BUFFER,
|
||||||
LIVESTREAM_STARTED_RECENTLY_BUFFER,
|
LIVESTREAM_STARTED_RECENTLY_BUFFER,
|
||||||
} from 'constants/livestream';
|
} from 'constants/livestream';
|
||||||
|
@ -98,16 +99,27 @@ export default function LivestreamPage(props: Props) {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [claim, uri, doCommentSocketConnect, doCommentSocketDisconnect]);
|
}, [claim, uri, doCommentSocketConnect, doCommentSocketDisconnect]);
|
||||||
|
|
||||||
// Find out current channels status + active live claim every 30 seconds
|
const claimReleaseStartingSoonStatic = () =>
|
||||||
|
release.isBetween(moment(), moment().add(LIVESTREAM_STARTS_SOON_BUFFER, 'minutes'));
|
||||||
|
|
||||||
|
const claimReleaseStartedRecentlyStatic = () =>
|
||||||
|
release.isBetween(moment().subtract(LIVESTREAM_STARTED_RECENTLY_BUFFER, 'minutes'), moment());
|
||||||
|
|
||||||
|
// Find out current channels status + active live claim every 30 seconds (or 15 if not live)
|
||||||
|
const fasterPoll = !isCurrentClaimLive && (claimReleaseStartingSoonStatic() || claimReleaseStartedRecentlyStatic());
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const fetch = () => doFetchChannelLiveStatus(livestreamChannelId);
|
const fetch = () => doFetchChannelLiveStatus(livestreamChannelId);
|
||||||
|
|
||||||
fetch();
|
fetch();
|
||||||
|
|
||||||
const intervalId = setInterval(fetch, LIVESTREAM_STATUS_CHECK_INTERVAL);
|
const intervalId = setInterval(
|
||||||
|
fetch,
|
||||||
|
fasterPoll ? LIVESTREAM_STATUS_CHECK_INTERVAL_SOON : LIVESTREAM_STATUS_CHECK_INTERVAL
|
||||||
|
);
|
||||||
|
|
||||||
return () => clearInterval(intervalId);
|
return () => clearInterval(intervalId);
|
||||||
}, [livestreamChannelId, doFetchChannelLiveStatus]);
|
}, [livestreamChannelId, doFetchChannelLiveStatus, fasterPoll]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setActiveStreamUri(!isCurrentClaimLive && isChannelBroadcasting ? activeLivestreamForChannel.claimUri : false);
|
setActiveStreamUri(!isCurrentClaimLive && isChannelBroadcasting ? activeLivestreamForChannel.claimUri : false);
|
||||||
|
@ -117,7 +129,6 @@ export default function LivestreamPage(props: Props) {
|
||||||
if (!isInitialized) return;
|
if (!isInitialized) return;
|
||||||
|
|
||||||
const claimReleaseInFuture = () => release.isAfter();
|
const claimReleaseInFuture = () => release.isAfter();
|
||||||
|
|
||||||
const claimReleaseInPast = () => release.isBefore();
|
const claimReleaseInPast = () => release.isBefore();
|
||||||
|
|
||||||
const claimReleaseStartingSoon = () =>
|
const claimReleaseStartingSoon = () =>
|
||||||
|
@ -127,7 +138,9 @@ export default function LivestreamPage(props: Props) {
|
||||||
release.isBetween(moment().subtract(LIVESTREAM_STARTED_RECENTLY_BUFFER, 'minutes'), moment());
|
release.isBetween(moment().subtract(LIVESTREAM_STARTED_RECENTLY_BUFFER, 'minutes'), moment());
|
||||||
|
|
||||||
const checkShowLivestream = () =>
|
const checkShowLivestream = () =>
|
||||||
isChannelBroadcasting && isCurrentClaimLive && (claimReleaseInPast() || claimReleaseStartingSoon());
|
isChannelBroadcasting &&
|
||||||
|
isCurrentClaimLive &&
|
||||||
|
(claimReleaseInPast() || claimReleaseStartingSoon() || claimReleaseInFuture());
|
||||||
|
|
||||||
const checkShowScheduledInfo = () =>
|
const checkShowScheduledInfo = () =>
|
||||||
(!isChannelBroadcasting && (claimReleaseInFuture() || claimReleaseStartedRecently())) ||
|
(!isChannelBroadcasting && (claimReleaseInFuture() || claimReleaseStartedRecently())) ||
|
||||||
|
@ -144,7 +157,7 @@ export default function LivestreamPage(props: Props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
calculateStreamReleaseState();
|
calculateStreamReleaseState();
|
||||||
const intervalId = setInterval(calculateStreamReleaseState, 1000);
|
const intervalId = setInterval(calculateStreamReleaseState, 5000);
|
||||||
|
|
||||||
if (isCurrentClaimLive && claimReleaseInPast() && isChannelBroadcasting === true) {
|
if (isCurrentClaimLive && claimReleaseInPast() && isChannelBroadcasting === true) {
|
||||||
clearInterval(intervalId);
|
clearInterval(intervalId);
|
||||||
|
|
|
@ -9,6 +9,10 @@ import {
|
||||||
filterUpcomingLiveStreamClaims,
|
filterUpcomingLiveStreamClaims,
|
||||||
} from 'util/livestream';
|
} from 'util/livestream';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import { isLocalStorageAvailable } from 'util/storage';
|
||||||
|
import { isEmpty } from 'util/object';
|
||||||
|
|
||||||
|
const localStorageAvailable = isLocalStorageAvailable();
|
||||||
|
|
||||||
const FETCH_ACTIVE_LIVESTREAMS_MIN_INTERVAL_MS = 5 * 60 * 1000;
|
const FETCH_ACTIVE_LIVESTREAMS_MIN_INTERVAL_MS = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
@ -100,26 +104,35 @@ const findActiveStreams = async (
|
||||||
// Find the first upcoming claim (if one exists) for each channel that's actively broadcasting a stream.
|
// Find the first upcoming claim (if one exists) for each channel that's actively broadcasting a stream.
|
||||||
const upcomingClaims = await dispatch(fetchUpcomingLivestreamClaims(channelIDs, lang));
|
const upcomingClaims = await dispatch(fetchUpcomingLivestreamClaims(channelIDs, lang));
|
||||||
|
|
||||||
// Filter out any of those claims that aren't scheduled to start within the configured "soon" buffer time (ex. next 5 min).
|
// Filter out any of those claims that aren't scheduled to start within the configured "soon" buffer time (ex. next 15 min).
|
||||||
const startingSoonClaims = filterUpcomingLiveStreamClaims(upcomingClaims);
|
const startingSoonClaims = filterUpcomingLiveStreamClaims(upcomingClaims);
|
||||||
|
|
||||||
// Reduce the claim list to one "live" claim per channel, based on how close each claim's
|
// Reduce the claim list to one "live" claim per channel, based on how close each claim's
|
||||||
// release time is to the time the channels stream started.
|
// release time is to the time the channels stream started.
|
||||||
const allClaims = Object.assign({}, mostRecentClaims, startingSoonClaims);
|
const allClaims = Object.assign(
|
||||||
|
{},
|
||||||
|
mostRecentClaims,
|
||||||
|
!isEmpty(startingSoonClaims) ? startingSoonClaims : upcomingClaims
|
||||||
|
);
|
||||||
|
|
||||||
return determineLiveClaim(allClaims, liveChannels);
|
return determineLiveClaim(allClaims, liveChannels);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const doFetchChannelLiveStatus = (channelId: string) => async (dispatch: Dispatch) => {
|
export const doFetchChannelLiveStatus = (channelId: string) => async (dispatch: Dispatch) => {
|
||||||
const statusForId = `live-status-${channelId}`;
|
const statusForId = `channel-live-status`;
|
||||||
// const localStatus = window.localStorage.getItem(statusForId);
|
const localStatus = localStorageAvailable && window.localStorage.getItem(statusForId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { channelStatus, channelData } = await fetchLiveChannel(channelId);
|
const { channelStatus, channelData } = await fetchLiveChannel(channelId);
|
||||||
|
// store live state locally, and force 2 non-live statuses before returninig NOT LIVE. This allows for the stream to finish before disposing player.
|
||||||
|
if (localStatus === LiveStatus.LIVE && channelStatus === LiveStatus.NOT_LIVE) {
|
||||||
|
localStorageAvailable && window.localStorage.removeItem(statusForId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (channelStatus === LiveStatus.NOT_LIVE) {
|
if (channelStatus === LiveStatus.NOT_LIVE && !localStatus) {
|
||||||
dispatch({ type: ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS, data: { channelId } });
|
dispatch({ type: ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS, data: { channelId } });
|
||||||
window.localStorage.removeItem(statusForId);
|
localStorageAvailable && window.localStorage.removeItem(statusForId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,10 +149,10 @@ export const doFetchChannelLiveStatus = (channelId: string) => async (dispatch:
|
||||||
dispatch({ type: ACTIONS.ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS, data: { ...channelData } });
|
dispatch({ type: ACTIONS.ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS, data: { ...channelData } });
|
||||||
}
|
}
|
||||||
|
|
||||||
window.localStorage.setItem(statusForId, channelStatus);
|
localStorageAvailable && window.localStorage.setItem(statusForId, channelStatus);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dispatch({ type: ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS, data: { channelId } });
|
dispatch({ type: ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS, data: { channelId } });
|
||||||
window.localStorage.removeItem(statusForId);
|
localStorageAvailable && window.localStorage.removeItem(statusForId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue