diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.component.scss b/client/src/app/+videos/+video-edit/shared/video-edit.component.scss index a81d62dd1..944d21caf 100644 --- a/client/src/app/+videos/+video-edit/shared/video-edit.component.scss +++ b/client/src/app/+videos/+video-edit/shared/video-edit.component.scss @@ -130,6 +130,7 @@ p-calendar { .position { height: 31px; + min-width: 16px; display: flex; align-items: center; } diff --git a/client/src/app/shared/shared-forms/timestamp-input.component.html b/client/src/app/shared/shared-forms/timestamp-input.component.html index c89a7b019..cea73852d 100644 --- a/client/src/app/shared/shared-forms/timestamp-input.component.html +++ b/client/src/app/shared/shared-forms/timestamp-input.component.html @@ -1,5 +1,5 @@ diff --git a/client/src/app/shared/shared-forms/timestamp-input.component.scss b/client/src/app/shared/shared-forms/timestamp-input.component.scss index df19240b4..5b5a6a5f6 100644 --- a/client/src/app/shared/shared-forms/timestamp-input.component.scss +++ b/client/src/app/shared/shared-forms/timestamp-input.component.scss @@ -26,6 +26,8 @@ p-inputmask { &:not(.border-disabled) { ::ng-deep input { @include peertube-input-text(80px); + + padding: 3px 10px; } } } diff --git a/client/src/app/shared/shared-forms/timestamp-input.component.ts b/client/src/app/shared/shared-forms/timestamp-input.component.ts index 280491852..d3ae91875 100644 --- a/client/src/app/shared/shared-forms/timestamp-input.component.ts +++ b/client/src/app/shared/shared-forms/timestamp-input.component.ts @@ -36,7 +36,8 @@ export class TimestampInputComponent implements ControlValueAccessor, OnInit { writeValue (timestamp: number) { this.timestamp = timestamp - this.timestampString = secondsToTime(this.timestamp, true, ':') + this.timestampString = secondsToTime({ seconds: this.timestamp, fullFormat: true, symbol: ':' }) + console.log(this.timestampString) } registerOnChange (fn: (_: any) => void) { diff --git a/client/src/app/shared/shared-video-playlist/video-playlist-element-miniature.component.ts b/client/src/app/shared/shared-video-playlist/video-playlist-element-miniature.component.ts index 16a1e51ca..d03e11e34 100644 --- a/client/src/app/shared/shared-video-playlist/video-playlist-element-miniature.component.ts +++ b/client/src/app/shared/shared-video-playlist/video-playlist-element-miniature.component.ts @@ -144,8 +144,8 @@ export class VideoPlaylistElementMiniatureComponent implements OnInit { const start = playlistElement.startTimestamp const stop = playlistElement.stopTimestamp - const startFormatted = secondsToTime(start, true, ':') - const stopFormatted = secondsToTime(stop, true, ':') + const startFormatted = secondsToTime({ seconds: start, fullFormat: true, symbol: ':' }) + const stopFormatted = secondsToTime({ seconds: stop, fullFormat: true, symbol: ':' }) if (start === null && stop === null) return '' diff --git a/client/src/assets/player/shared/peertube/peertube-plugin.ts b/client/src/assets/player/shared/peertube/peertube-plugin.ts index 3587a3e92..80b767024 100644 --- a/client/src/assets/player/shared/peertube/peertube-plugin.ts +++ b/client/src/assets/player/shared/peertube/peertube-plugin.ts @@ -229,7 +229,7 @@ class PeerTubePlugin extends Plugin { // In portrait screen mode, we allow player with bigger height size than width const portraitMode = getComputedStyle(el).getPropertyValue(this.options.autoPlayerRatio.cssPlayerPortraitModeVariable) === '1' - const currentRatio = !portraitMode && data.ratio < 1 + const currentRatio = isNaN(data.ratio) || (!portraitMode && data.ratio < 1) ? defaultRatio : data.ratio diff --git a/packages/core-utils/src/common/date.ts b/packages/core-utils/src/common/date.ts index 8cf5ac5db..f3f0d4c65 100644 --- a/packages/core-utils/src/common/date.ts +++ b/packages/core-utils/src/common/date.ts @@ -83,29 +83,46 @@ function timeToInt (time: number | string) { return result } -function secondsToTime (seconds: number, full = false, symbol?: string) { +function secondsToTime (options: { + seconds: number + fullFormat?: boolean // default false + symbol?: string +} | number) { + let seconds: number + let fullFormat = false + let symbol: string + + if (typeof options === 'number') { + seconds = options + } else { + seconds = options.seconds + fullFormat = options.fullFormat ?? false + symbol = options.symbol + } + let time = '' - if (seconds === 0 && !full) return '0s' + if (seconds === 0 && !fullFormat) return '0s' const hourSymbol = (symbol || 'h') const minuteSymbol = (symbol || 'm') - const secondsSymbol = full ? '' : 's' + const secondsSymbol = fullFormat ? '' : 's' const hours = Math.floor(seconds / 3600) - if (hours >= 1) time = hours + hourSymbol - else if (full) time = '0' + hourSymbol + if (hours >= 1 && hours < 10 && fullFormat) time = '0' + hours + hourSymbol + else if (hours >= 1) time = hours + hourSymbol + else if (fullFormat) time = '00' + hourSymbol seconds %= 3600 const minutes = Math.floor(seconds / 60) - if (minutes >= 1 && minutes < 10 && full) time += '0' + minutes + minuteSymbol + if (minutes >= 1 && minutes < 10 && fullFormat) time += '0' + minutes + minuteSymbol else if (minutes >= 1) time += minutes + minuteSymbol - else if (full) time += '00' + minuteSymbol + else if (fullFormat) time += '00' + minuteSymbol seconds %= 60 - if (seconds >= 1 && seconds < 10 && full) time += '0' + seconds + secondsSymbol + if (seconds >= 1 && seconds < 10 && fullFormat) time += '0' + seconds + secondsSymbol else if (seconds >= 1) time += seconds + secondsSymbol - else if (full) time += '00' + else if (fullFormat) time += '00' return time } diff --git a/server/core/lib/job-queue/handlers/video-live-ending.ts b/server/core/lib/job-queue/handlers/video-live-ending.ts index ee1a3b2c4..eecb931c8 100644 --- a/server/core/lib/job-queue/handlers/video-live-ending.ts +++ b/server/core/lib/job-queue/handlers/video-live-ending.ts @@ -61,6 +61,12 @@ async function processVideoLiveEnding (job: Job) { return cleanupLiveAndFederate({ permanentLive, video, streamingPlaylistId: payload.streamingPlaylistId }) } + if (await hasReplayFiles(payload.replayDirectory) !== true) { + logger.info(`No replay files found for live ${video.uuid}, skipping video replay creation.`, { ...lTags(video.uuid) }) + + return cleanupLiveAndFederate({ permanentLive, video, streamingPlaylistId: payload.streamingPlaylistId }) + } + if (permanentLive) { await saveReplayToExternalVideo({ liveVideo: video, @@ -305,3 +311,7 @@ async function cleanupLiveAndFederate (options: { function createStoryboardJob (video: MVideo) { return JobQueue.Instance.createJob(buildStoryboardJobIfNeeded({ video, federate: true })) } + +async function hasReplayFiles (replayDirectory: string) { + return (await readdir(replayDirectory)).length !== 0 +}