Skip to content

Commit

Permalink
Merge branch 'release/6.3.0' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Chocobozzz committed Oct 8, 2024
2 parents 714f7ae + c9856e7 commit 47a7007
Show file tree
Hide file tree
Showing 17 changed files with 109 additions and 29 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## v6.3.2

### Bug fixes

* Fix 403 error when downloading private/internal video
* Don't crash video federation and live replay generation on missing thumbnail/preview
* Fix advanced search input with multiple automatic search tokens
* Fix player "Copy URL" when the video is fullscreen
* Fix account videos search
* Add missing max transcoding fps config in admin
* Don't add mobile buttons if the player controls are disabled


## v6.3.1

### IMPORTANT NOTES
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "peertube-client",
"version": "6.3.1",
"version": "6.3.2",
"private": true,
"license": "AGPL-3.0",
"author": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
SERVICES_TWITTER_USERNAME_VALIDATOR,
SIGNUP_LIMIT_VALIDATOR,
SIGNUP_MINIMUM_AGE_VALIDATOR,
TRANSCODING_MAX_FPS_VALIDATOR,
TRANSCODING_THREADS_VALIDATOR
} from '@app/shared/form-validators/custom-config-validators'
import { USER_VIDEO_QUOTA_DAILY_VALIDATOR, USER_VIDEO_QUOTA_VALIDATOR } from '@app/shared/form-validators/user-validators'
Expand Down Expand Up @@ -241,6 +242,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
},
remoteRunners: {
enabled: null
},
fps: {
max: TRANSCODING_MAX_FPS_VALIDATOR
}
},
live: {
Expand All @@ -262,6 +266,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
alwaysTranscodeOriginalResolution: null,
remoteRunners: {
enabled: null
},
fps: {
max: TRANSCODING_MAX_FPS_VALIDATOR
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ <h2 i18n>LIVE</h2>
<div class="form-group" [ngClass]="getDisabledLiveClass()">
<label i18n for="liveMaxInstanceLives">Max simultaneous lives created on your instance</label>

<span class="ms-2 small muted">(-1 for "unlimited")</span>
<span i18n class="ms-2 small muted">(-1 for "unlimited")</span>

<div class="number-with-unit">
<input type="number" id="liveMaxInstanceLives" formControlName="maxInstanceLives" />
Expand All @@ -60,7 +60,7 @@ <h2 i18n>LIVE</h2>

<div class="form-group" [ngClass]="getDisabledLiveClass()">
<label i18n for="liveMaxUserLives">Max simultaneous lives created per user</label>
<span class="ms-2 small muted">(-1 for "unlimited")</span>
<span i18n class="ms-2 small muted">(-1 for "unlimited")</span>

<div class="number-with-unit">
<input type="number" id="liveMaxUserLives" formControlName="maxUserLives" />
Expand Down Expand Up @@ -113,6 +113,19 @@ <h3 class="callout-title" i18n>Output formats</h3>

<div [ngClass]="getDisabledLiveTranscodingClass()">

<div class="form-group" formGroupName="fps">
<label i18n for="liveTranscodingFPSMax">Max live FPS</label>

<span i18n class="ms-2 small muted">Cap transcoded live FPS. Max resolution stream still keeps the original FPS.</span>

<div class="number-with-unit">
<input type="number" name="liveTranscodingFPSMax" formControlName="max" />
<span>FPS</span>
</div>

<div *ngIf="formErrors.live.transcoding.fps.max" class="form-error" role="alert">{{ formErrors.live.transcoding.fps.max }}</div>
</div>

<div class="ms-2 mt-3">
<h4 i18n>Live resolutions to generate</h4>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,19 @@ <h3 class="callout-title" i18n>Output</h3>
</div>
</ng-container>

<div class="form-group" formGroupName="fps" [ngClass]="getTranscodingDisabledClass()">
<label i18n for="transcodingFPSMax">Max video FPS</label>

<span i18n class="ms-2 small muted">Cap transcoded video FPS. Max resolution file still keeps the original FPS.</span>

<div class="number-with-unit">
<input type="number" name="transcodingFPSMax" formControlName="max" />
<span>FPS</span>
</div>

<div *ngIf="formErrors.transcoding.fps.max" class="form-error" role="alert">{{ formErrors.transcoding.fps.max }}</div>
</div>

<div class="form-group" [ngClass]="getTranscodingDisabledClass()">
<div class="mb-2 fw-bold" i18n>Resolutions to generate</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ export const TRANSCODING_THREADS_VALIDATOR: BuildFormValidator = {
}
}

export const TRANSCODING_MAX_FPS_VALIDATOR: BuildFormValidator = {
VALIDATORS: [ Validators.required, Validators.min(1) ],
MESSAGES: {
required: $localize`Transcoding max FPS is required.`,
min: $localize`Transcoding max FPS must be greater or equal to 1.`
}
}

export const MAX_LIVE_DURATION_VALIDATOR: BuildFormValidator = {
VALIDATORS: [ Validators.required, Validators.min(-1) ],
MESSAGES: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,25 +155,30 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit {
}

private addFilterToSearch (search: string, newFilter: AdvancedInputFilterChild) {
const prefix = newFilter.value.split(':').shift()
const filterTokens = this.restService.tokenizeString(newFilter.value)
let searchTokens = this.restService.tokenizeString(search)

// Tokenize search and remove a potential existing filter
const tokens = this.restService.tokenizeString(search)
.filter(t => !t.startsWith(prefix))
for (const filterToken of filterTokens) {
const prefix = filterToken.split(':').shift()

tokens.push(newFilter.value)
// Tokenize search and remove a potential existing filter
searchTokens = searchTokens.filter(t => !t.startsWith(prefix))
searchTokens.push(filterToken)
}

return tokens.join(' ')
return searchTokens.join(' ')
}

private parseFilters (search: string) {
const tokens = this.restService.tokenizeString(search)
const searchTokens = this.restService.tokenizeString(search)

this.enabledFilters = new Set()

for (const group of this.filters) {
for (const filter of group.children) {
if (tokens.includes(filter.value)) {
const filterTokens = this.restService.tokenizeString(filter.value)

if (filterTokens.every(filterToken => searchTokens.includes(filterToken))) {
this.enabledFilters.add(filter.value)
}
}
Expand Down
5 changes: 4 additions & 1 deletion client/src/app/shared/shared-main/video/video.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,17 @@ export class VideoService {
generateDownloadUrl (options: {
video: Video
files: VideoFile[]
videoFileToken?: string
}) {
const { video, files } = options
const { video, files, videoFileToken } = options

if (files.length === 0) throw new Error('Cannot generate download URL without files')

let url = `${VideoService.BASE_VIDEO_DOWNLOAD_URL}/${video.uuid}?`
url += files.map(f => 'videoFileIds=' + f.id).join('&')

if (videoFileToken) url += `&videoFileToken=${videoFileToken}`

return url
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class UserVideoSettingsComponent extends FormReactive implements OnInit,
next: () => {
this.authService.refreshUserInformation()

if (this.notifyOnUpdate) this.notifier.success($localize`Video settings updated.`, 'toto', 15000)
if (this.notifyOnUpdate) this.notifier.success($localize`Video settings updated.`)
},

error: err => this.notifier.error(err.message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class VideoGenerateDownloadComponent implements OnInit {
files.push(this.findAudioFileOnly())
}

return this.videoService.generateDownloadUrl({ video: this.video, files })
return this.videoService.generateDownloadUrl({ video: this.video, videoFileToken: this.videoFileToken, files })
}

// ---------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export class VideoFilters {
[ 'categoryOneOf', undefined ],
[ 'scope', 'federated' ],
[ 'allVideos', false ],
[ 'live', 'both' ]
[ 'live', 'both' ],
[ 'search', '' ]
])

private activeFilters: VideoFilterActive[] = []
Expand Down
12 changes: 6 additions & 6 deletions client/src/assets/player/peertube-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,25 +502,25 @@ export class PeerTubePlayer {
{
label: player.localize('Copy the video URL'),
listener: function () {
copyToClipboard(buildVideoLink({ shortUUID }))
copyToClipboard(buildVideoLink({ shortUUID }), player.el() as HTMLElement)
}
},
{
label: player.localize('Copy the video URL at the current time'),
listener: function () {
const url = buildVideoLink({ shortUUID })

copyToClipboard(decorateVideoLink({ url, startTime: player.currentTime() }))
copyToClipboard(decorateVideoLink({ url, startTime: player.currentTime() }), player.el() as HTMLElement)
}
},
{
icon: 'code',
label: player.localize('Copy embed code'),
listener: () => {
copyToClipboard(buildVideoOrPlaylistEmbed({
embedUrl: self.currentLoadOptions.embedUrl,
embedTitle: self.currentLoadOptions.embedTitle
}))
copyToClipboard(
buildVideoOrPlaylistEmbed({ embedUrl: self.currentLoadOptions.embedUrl, embedTitle: self.currentLoadOptions.embedTitle }),
player.el() as HTMLElement
)
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@ class PeerTubeMobilePlugin extends Plugin {

this.seekAmount = 0

this.peerTubeMobileButtons = player.addChild('PeerTubeMobileButtons', { reportTouchActivity: false }) as PeerTubeMobileButtons

if (videojs.browser.IS_ANDROID && screen.orientation) {
this.handleFullscreenRotation()
}

// Don't add buttons if the player doesn't have controls
if (!player.controls()) return

this.peerTubeMobileButtons = player.addChild('PeerTubeMobileButtons', { reportTouchActivity: false }) as PeerTubeMobileButtons

if (!this.player.options_.userActions) this.player.options_.userActions = {};

// FIXME: typings
Expand Down
8 changes: 5 additions & 3 deletions client/src/root-helpers/utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
function copyToClipboard (text: string) {
function copyToClipboard (text: string, container?: HTMLElement) {
if (!container) container = document.body

const el = document.createElement('textarea')
el.value = text
el.setAttribute('readonly', '')
el.style.position = 'absolute'
el.style.left = '-9999px'
document.body.appendChild(el)
container.appendChild(el)
el.select()
document.execCommand('copy')
document.body.removeChild(el)
container.removeChild(el)
}

function wait (ms: number) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "peertube",
"description": "PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.",
"version": "6.3.1",
"version": "6.3.2",
"private": true,
"licence": "AGPL-3.0",
"engines": {
Expand Down
15 changes: 13 additions & 2 deletions server/core/lib/job-queue/handlers/video-live-ending.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,14 @@ async function saveReplayToExternalVideo (options: {
inputFileMutexReleaser()
}

await copyOrRegenerateThumbnails({ liveVideo, replayVideo })
try {
await copyOrRegenerateThumbnails({ liveVideo, replayVideo })
} catch (err) {
logger.error(
`Cannot copy/regenerate thumbnails of ended live ${liveVideo.uuid} to external video ${replayVideo.uuid}`,
lTags(liveVideo.uuid, replayVideo.uuid)
)
}

await createStoryboardJob(replayVideo)
await createTranscriptionTaskIfNeeded(replayVideo)
Expand Down Expand Up @@ -280,7 +287,11 @@ async function replaceLiveByReplay (options: {
}

// Regenerate the thumbnail & preview?
await regenerateMiniaturesIfNeeded(videoWithFiles, undefined)
try {
await regenerateMiniaturesIfNeeded(videoWithFiles, undefined)
} catch (err) {
logger.error(`Cannot regenerate thumbnails of ended live ${videoWithFiles.uuid}`, lTags(liveVideo.uuid))
}

// We consider this is a new video
await moveToNextState({ video: videoWithFiles, isNewVideo: true })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ function buildTags (video: MVideoAP) {

function buildIcon (video: MVideoAP): ActivityIconObject[] {
return [ video.getMiniature(), video.getPreview() ]
.filter(i => !!i)
.map(i => i.toActivityPubObject(video))
}

Expand Down

0 comments on commit 47a7007

Please sign in to comment.