Prefer web videos in favour of webtorrent

This commit is contained in:
Chocobozzz 2023-07-11 09:21:13 +02:00
parent c3030e944a
commit 784e2ad5c3
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
102 changed files with 579 additions and 570 deletions

View File

@ -116,7 +116,7 @@ Be it as a user or an instance administrator, you can decide what your experienc
<h3 align="right">Communities that help each other</h3> <h3 align="right">Communities that help each other</h3>
<p align="right"> <p align="right">
In addition to visitors using WebTorrent to share the load among them, instances can help each other by caching one another's videos. This way even small instances have a way to show content to a wider audience, as they will be shouldered by friend instances (more about that in our <a href="https://docs.joinpeertube.org/contribute/architecture#redundancy-between-instances">redundancy guide</a>). In addition to visitors using P2P with WebRTC to share the load among them, instances can help each other by caching one another's videos. This way even small instances have a way to show content to a wider audience, as they will be shouldered by friend instances (more about that in our <a href="https://docs.joinpeertube.org/contribute/architecture#redundancy-between-instances">redundancy guide</a>).
</p> </p>
<p align="right"> <p align="right">
Content creators can get help from their viewers in the simplest way possible: a support button showing a message linking to their donation accounts or really anything else. No more pay-per-view and advertisements that hurt visitors and alter creativity (more about that in our <a href="https://github.com/Chocobozzz/PeerTube/blob/develop/FAQ.md">FAQ</a>). Content creators can get help from their viewers in the simplest way possible: a support button showing a message linking to their donation accounts or really anything else. No more pay-per-view and advertisements that hurt visitors and alter creativity (more about that in our <a href="https://github.com/Chocobozzz/PeerTube/blob/develop/FAQ.md">FAQ</a>).

View File

@ -31,8 +31,8 @@ describe('Private videos all workflow', () => {
return loginPage.loginOnPeerTube2() return loginPage.loginOnPeerTube2()
}) })
it('Should play an internal webtorrent video', async () => { it('Should play an internal web video video', async () => {
await go(FIXTURE_URLS.INTERNAL_WEBTORRENT_VIDEO) await go(FIXTURE_URLS.INTERNAL_WEB_VIDEO)
await videoWatchPage.waitWatchVideoName(internalVideoName) await videoWatchPage.waitWatchVideoName(internalVideoName)
await checkCorrectlyPlay(playerPage) await checkCorrectlyPlay(playerPage)
@ -52,8 +52,8 @@ describe('Private videos all workflow', () => {
await checkCorrectlyPlay(playerPage) await checkCorrectlyPlay(playerPage)
}) })
it('Should play an internal WebTorrent video in embed', async () => { it('Should play an internal Web Video in embed', async () => {
await go(FIXTURE_URLS.INTERNAL_EMBED_WEBTORRENT_VIDEO) await go(FIXTURE_URLS.INTERNAL_EMBED_WEB_VIDEO)
await videoWatchPage.waitEmbedForDisplayed() await videoWatchPage.waitEmbedForDisplayed()
await checkCorrectlyPlay(playerPage) await checkCorrectlyPlay(playerPage)

View File

@ -89,7 +89,7 @@ describe('Videos all workflow', () => {
let videoNameToExcept = videoName let videoNameToExcept = videoName
if (isMobileDevice() || isSafari()) { if (isMobileDevice() || isSafari()) {
await go(FIXTURE_URLS.WEBTORRENT_VIDEO) await go(FIXTURE_URLS.WEB_VIDEO)
videoNameToExcept = 'E2E tests' videoNameToExcept = 'E2E tests'
} else { } else {
await videoListPage.clickOnVideo(videoName) await videoListPage.clickOnVideo(videoName)
@ -176,7 +176,7 @@ describe('Videos all workflow', () => {
await videoWatchPage.waitUntilVideoName(video2Name, 40 * 1000) await videoWatchPage.waitUntilVideoName(video2Name, 40 * 1000)
}) })
it('Should watch the webtorrent playlist in the embed', async () => { it('Should watch the WEB VIDEO playlist in the embed', async () => {
if (isUploadUnsupported()) return if (isUploadUnsupported()) return
const accessToken = await browser.execute(`return window.localStorage.getItem('access_token');`) const accessToken = await browser.execute(`return window.localStorage.getItem('access_token');`)

View File

@ -1,14 +1,14 @@
const FIXTURE_URLS = { const FIXTURE_URLS = {
INTERNAL_WEBTORRENT_VIDEO: 'https://peertube2.cpy.re/w/pwfz7NizSdPD4mJcbbmNwa?mode=webtorrent&start=0', INTERNAL_WEB_VIDEO: 'https://peertube2.cpy.re/w/pwfz7NizSdPD4mJcbbmNwa?mode=web-video&start=0',
INTERNAL_HLS_VIDEO: 'https://peertube2.cpy.re/w/pwfz7NizSdPD4mJcbbmNwa?start=0', INTERNAL_HLS_VIDEO: 'https://peertube2.cpy.re/w/pwfz7NizSdPD4mJcbbmNwa?start=0',
INTERNAL_EMBED_WEBTORRENT_VIDEO: 'https://peertube2.cpy.re/videos/embed/pwfz7NizSdPD4mJcbbmNwa?mode=webtorrent&start=0', INTERNAL_EMBED_WEB_VIDEO: 'https://peertube2.cpy.re/videos/embed/pwfz7NizSdPD4mJcbbmNwa?mode=web-video&start=0',
INTERNAL_EMBED_HLS_VIDEO: 'https://peertube2.cpy.re/videos/embed/pwfz7NizSdPD4mJcbbmNwa?start=0', INTERNAL_EMBED_HLS_VIDEO: 'https://peertube2.cpy.re/videos/embed/pwfz7NizSdPD4mJcbbmNwa?start=0',
INTERNAL_HLS_ONLY_VIDEO: 'https://peertube2.cpy.re/w/tKQmHcqdYZRdCszLUiWM3V?start=0', INTERNAL_HLS_ONLY_VIDEO: 'https://peertube2.cpy.re/w/tKQmHcqdYZRdCszLUiWM3V?start=0',
INTERNAL_EMBED_HLS_ONLY_VIDEO: 'https://peertube2.cpy.re/videos/embed/tKQmHcqdYZRdCszLUiWM3V?start=0', INTERNAL_EMBED_HLS_ONLY_VIDEO: 'https://peertube2.cpy.re/videos/embed/tKQmHcqdYZRdCszLUiWM3V?start=0',
WEBTORRENT_VIDEO: 'https://peertube2.cpy.re/w/122d093a-1ede-43bd-bd34-59d2931ffc5e', WEB_VIDEO: 'https://peertube2.cpy.re/w/122d093a-1ede-43bd-bd34-59d2931ffc5e',
HLS_EMBED: 'https://peertube2.cpy.re/videos/embed/969bf103-7818-43b5-94a0-de159e13de50', HLS_EMBED: 'https://peertube2.cpy.re/videos/embed/969bf103-7818-43b5-94a0-de159e13de50',
HLS_PLAYLIST_EMBED: 'https://peertube2.cpy.re/video-playlists/embed/73804a40-da9a-40c2-b1eb-2c6d9eec8f0a', HLS_PLAYLIST_EMBED: 'https://peertube2.cpy.re/video-playlists/embed/73804a40-da9a-40c2-b1eb-2c6d9eec8f0a',

View File

@ -24,19 +24,19 @@ module.exports = {
specFileRetries: 0, specFileRetries: 0,
capabilities: [ capabilities: [
{ // {
'browserName': 'chrome', // 'browserName': 'chrome',
'acceptInsecureCerts': true, // 'acceptInsecureCerts': true,
'goog:chromeOptions': { // 'goog:chromeOptions': {
args: [ '--disable-gpu', windowSizeArg ], // args: [ '--disable-gpu', windowSizeArg ],
prefs // prefs
} // }
}, // },
{ {
'browserName': 'firefox', 'browserName': 'firefox',
'moz:firefoxOptions': { 'moz:firefoxOptions': {
binary: '/usr/bin/firefox-developer-edition', binary: '/usr/bin/firefox-developer-edition',
args: [ '--headless', windowSizeArg ], // args: [ '--headless', windowSizeArg ],
prefs prefs
} }

View File

@ -71,7 +71,7 @@
<div class="form-group" [ngClass]="getTranscodingDisabledClass()"> <div class="form-group" [ngClass]="getTranscodingDisabledClass()">
<my-peertube-checkbox <my-peertube-checkbox
inputName="transcodingWebTorrentEnabled" formControlName="enabled" inputName="transcodingWebTorrentEnabled" formControlName="enabled"
i18n-labelText labelText="WebTorrent enabled" i18n-labelText labelText="Web Videos enabled"
> >
<ng-template ptTemplate="help"> <ng-template ptTemplate="help">
<ng-container> <ng-container>
@ -93,14 +93,14 @@
<ng-container i18n> <ng-container i18n>
<strong>Requires ffmpeg >= 4.1</strong> <strong>Requires ffmpeg >= 4.1</strong>
<p>Generate HLS playlists and fragmented MP4 files resulting in a better playback than with plain WebTorrent:</p> <p>Generate HLS playlists and fragmented MP4 files resulting in a better playback than with Web Videos:</p>
<ul> <ul>
<li>Resolution change is smoother</li> <li>Resolution change is smoother</li>
<li>Faster playback especially with long videos</li> <li>Faster playback especially with long videos</li>
<li>More stable playback (less bugs/infinite loading)</li> <li>More stable playback (less bugs/infinite loading)</li>
</ul> </ul>
<p>If you also enabled WebTorrent support, it will multiply videos storage by 2</p> <p>If you also enabled Web Videos support, it will multiply videos storage by 2</p>
</ng-container> </ng-container>
</ng-template> </ng-template>
</my-peertube-checkbox> </my-peertube-checkbox>

View File

@ -59,12 +59,12 @@ export class VideoAdminService {
title: $localize`Video files`, title: $localize`Video files`,
children: [ children: [
{ {
value: 'webtorrent:true isLocal:true', value: 'webVideos:true isLocal:true',
label: $localize`With WebTorrent` label: $localize`With Web Videos`
}, },
{ {
value: 'webtorrent:false isLocal:true', value: 'webVideos:false isLocal:true',
label: $localize`Without WebTorrent` label: $localize`Without Web Videos`
}, },
{ {
value: 'hls:true isLocal:true', value: 'hls:true isLocal:true',
@ -126,8 +126,8 @@ export class VideoAdminService {
prefix: 'hls:', prefix: 'hls:',
isBoolean: true isBoolean: true
}, },
hasWebtorrentFiles: { hasWebVideoFiles: {
prefix: 'webtorrent:', prefix: 'webVideos:',
isBoolean: true isBoolean: true
}, },
isLive: { isLive: {

View File

@ -83,8 +83,8 @@
</td> </td>
<td> <td>
<span *ngIf="isHLS(video)" class="pt-badge badge-blue">HLS</span> <span *ngIf="hasHLS(video)" class="pt-badge badge-blue">HLS</span>
<span *ngIf="isWebTorrent(video)" class="pt-badge badge-blue">WebTorrent ({{ video.files.length }})</span> <span *ngIf="hasWebVideos(video)" class="pt-badge badge-blue">Web Videos ({{ video.files.length }})</span>
<span i18n *ngIf="video.isLive" class="pt-badge badge-blue">Live</span> <span i18n *ngIf="video.isLive" class="pt-badge badge-blue">Live</span>
<span i18n *ngIf="hasObjectStorage(video)" class="pt-badge badge-purple">Object storage</span> <span i18n *ngIf="hasObjectStorage(video)" class="pt-badge badge-purple">Object storage</span>
@ -102,8 +102,8 @@
<tr> <tr>
<td class="video-info expand-cell" myAutoColspan> <td class="video-info expand-cell" myAutoColspan>
<div> <div>
<div *ngIf="isWebTorrent(video)"> <div *ngIf="hasWebVideos(video)">
WebTorrent: Web Videos:
<ul> <ul>
<li *ngFor="let file of video.files"> <li *ngFor="let file of video.files">
@ -112,13 +112,13 @@
<my-global-icon <my-global-icon
*ngIf="canRemoveOneFile(video)" *ngIf="canRemoveOneFile(video)"
i18n-ngbTooltip ngbTooltip="Delete this file" iconName="delete" role="button" i18n-ngbTooltip ngbTooltip="Delete this file" iconName="delete" role="button"
(click)="removeVideoFile(video, file, 'webtorrent')" (click)="removeVideoFile(video, file, 'web-videos')"
></my-global-icon> ></my-global-icon>
</li> </li>
</ul> </ul>
</div> </div>
<div *ngIf="isHLS(video)"> <div *ngIf="hasHLS(video)">
HLS: HLS:
<ul> <ul>

View File

@ -99,8 +99,8 @@ export class VideoListComponent extends RestTable <Video> implements OnInit {
iconName: 'cog' iconName: 'cog'
}, },
{ {
label: $localize`Run WebTorrent transcoding`, label: $localize`Run Web Video transcoding`,
handler: videos => this.runTranscoding(videos, 'webtorrent'), handler: videos => this.runTranscoding(videos, 'web-video'),
isDisplayed: videos => videos.every(v => v.canRunTranscoding(this.authUser)), isDisplayed: videos => videos.every(v => v.canRunTranscoding(this.authUser)),
iconName: 'cog' iconName: 'cog'
}, },
@ -111,8 +111,8 @@ export class VideoListComponent extends RestTable <Video> implements OnInit {
iconName: 'delete' iconName: 'delete'
}, },
{ {
label: $localize`Delete WebTorrent files`, label: $localize`Delete Web Video files`,
handler: videos => this.removeVideoFiles(videos, 'webtorrent'), handler: videos => this.removeVideoFiles(videos, 'web-videos'),
isDisplayed: videos => videos.every(v => v.canRemoveFiles(this.authUser)), isDisplayed: videos => videos.every(v => v.canRemoveFiles(this.authUser)),
iconName: 'delete' iconName: 'delete'
} }
@ -150,14 +150,14 @@ export class VideoListComponent extends RestTable <Video> implements OnInit {
return video.state.id === VideoState.TO_IMPORT return video.state.id === VideoState.TO_IMPORT
} }
isHLS (video: Video) { hasHLS (video: Video) {
const p = video.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS) const p = video.streamingPlaylists.find(p => p.type === VideoStreamingPlaylistType.HLS)
if (!p) return false if (!p) return false
return p.files.length !== 0 return p.files.length !== 0
} }
isWebTorrent (video: Video) { hasWebVideos (video: Video) {
return video.files.length !== 0 return video.files.length !== 0
} }
@ -176,14 +176,14 @@ export class VideoListComponent extends RestTable <Video> implements OnInit {
getFilesSize (video: Video) { getFilesSize (video: Video) {
let files = video.files let files = video.files
if (this.isHLS(video)) { if (this.hasHLS(video)) {
files = files.concat(video.streamingPlaylists[0].files) files = files.concat(video.streamingPlaylists[0].files)
} }
return files.reduce((p, f) => p += f.size, 0) return files.reduce((p, f) => p += f.size, 0)
} }
async removeVideoFile (video: Video, file: VideoFile, type: 'hls' | 'webtorrent') { async removeVideoFile (video: Video, file: VideoFile, type: 'hls' | 'web-videos') {
const message = $localize`Are you sure you want to delete this ${file.resolution.label} file?` const message = $localize`Are you sure you want to delete this ${file.resolution.label} file?`
const res = await this.confirmService.confirm(message, $localize`Delete file`) const res = await this.confirmService.confirm(message, $localize`Delete file`)
if (res === false) return if (res === false) return
@ -262,7 +262,7 @@ export class VideoListComponent extends RestTable <Video> implements OnInit {
}) })
} }
private async removeVideoFiles (videos: Video[], type: 'hls' | 'webtorrent') { private async removeVideoFiles (videos: Video[], type: 'hls' | 'web-videos') {
let message: string let message: string
if (type === 'hls') { if (type === 'hls') {
@ -274,7 +274,7 @@ export class VideoListComponent extends RestTable <Video> implements OnInit {
} else { } else {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
message = formatICU( message = formatICU(
$localize`Are you sure you want to delete WebTorrent files of {count, plural, =1 {1 video} other {{count} videos}}?`, $localize`Are you sure you want to delete Web Video files of {count, plural, =1 {1 video} other {{count} videos}}?`,
{ count: videos.length } { count: videos.length }
) )
} }
@ -293,7 +293,7 @@ export class VideoListComponent extends RestTable <Video> implements OnInit {
}) })
} }
private runTranscoding (videos: Video[], type: 'hls' | 'webtorrent') { private runTranscoding (videos: Video[], type: 'hls' | 'web-video') {
this.videoService.runTranscoding(videos.map(v => v.id), type) this.videoService.runTranscoding(videos.map(v => v.id), type)
.subscribe({ .subscribe({
next: () => { next: () => {

View File

@ -30,8 +30,6 @@ export class User implements UserServerModel {
autoPlayNextVideoPlaylist: boolean autoPlayNextVideoPlaylist: boolean
p2pEnabled: boolean p2pEnabled: boolean
// FIXME: deprecated in 4.1
webTorrentEnabled: never
videosHistoryEnabled: boolean videosHistoryEnabled: boolean
videoLanguages: string[] videoLanguages: string[]

View File

@ -252,7 +252,7 @@ export class Video implements VideoServerModel {
user && user.hasRight(UserRight.MANAGE_VIDEO_FILES) && user && user.hasRight(UserRight.MANAGE_VIDEO_FILES) &&
this.state.id !== VideoState.TO_TRANSCODE && this.state.id !== VideoState.TO_TRANSCODE &&
this.hasHLS() && this.hasHLS() &&
this.hasWebTorrent() this.hasWebVideos()
} }
canRunTranscoding (user: AuthUser) { canRunTranscoding (user: AuthUser) {
@ -265,7 +265,7 @@ export class Video implements VideoServerModel {
return this.streamingPlaylists?.some(p => p.type === VideoStreamingPlaylistType.HLS) return this.streamingPlaylists?.some(p => p.type === VideoStreamingPlaylistType.HLS)
} }
hasWebTorrent () { hasWebVideos () {
return this.files && this.files.length !== 0 return this.files && this.files.length !== 0
} }

View File

@ -311,7 +311,7 @@ export class VideoService {
) )
} }
removeVideoFiles (videoIds: (number | string)[], type: 'hls' | 'webtorrent') { removeVideoFiles (videoIds: (number | string)[], type: 'hls' | 'web-videos') {
return from(videoIds) return from(videoIds)
.pipe( .pipe(
concatMap(id => this.authHttp.delete(VideoService.BASE_VIDEO_URL + '/' + id + '/' + type)), concatMap(id => this.authHttp.delete(VideoService.BASE_VIDEO_URL + '/' + id + '/' + type)),
@ -320,12 +320,12 @@ export class VideoService {
) )
} }
removeFile (videoId: number | string, fileId: number, type: 'hls' | 'webtorrent') { removeFile (videoId: number | string, fileId: number, type: 'hls' | 'web-videos') {
return this.authHttp.delete(VideoService.BASE_VIDEO_URL + '/' + videoId + '/' + type + '/' + fileId) return this.authHttp.delete(VideoService.BASE_VIDEO_URL + '/' + videoId + '/' + type + '/' + fileId)
.pipe(catchError(err => this.restExtractor.handleError(err))) .pipe(catchError(err => this.restExtractor.handleError(err)))
} }
runTranscoding (videoIds: (number | string)[], type: 'hls' | 'webtorrent') { runTranscoding (videoIds: (number | string)[], type: 'hls' | 'web-video') {
const body: VideoTranscodingCreate = { transcodingType: type } const body: VideoTranscodingCreate = { transcodingType: type }
return from(videoIds) return from(videoIds)

View File

@ -273,7 +273,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
}) })
} }
async removeVideoFiles (video: Video, type: 'hls' | 'webtorrent') { async removeVideoFiles (video: Video, type: 'hls' | 'web-videos') {
const confirmMessage = $localize`Do you really want to remove "${this.video.name}" files?` const confirmMessage = $localize`Do you really want to remove "${this.video.name}" files?`
const res = await this.confirmService.confirm(confirmMessage, $localize`Remove "${this.video.name}" files`) const res = await this.confirmService.confirm(confirmMessage, $localize`Remove "${this.video.name}" files`)
@ -290,7 +290,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
}) })
} }
runTranscoding (video: Video, type: 'hls' | 'webtorrent') { runTranscoding (video: Video, type: 'hls' | 'web-video') {
this.videoService.runTranscoding([ video.id ], type) this.videoService.runTranscoding([ video.id ], type)
.subscribe({ .subscribe({
next: () => { next: () => {
@ -394,8 +394,8 @@ export class VideoActionsDropdownComponent implements OnChanges {
iconName: 'cog' iconName: 'cog'
}, },
{ {
label: $localize`Run WebTorrent transcoding`, label: $localize`Run Web Video transcoding`,
handler: ({ video }) => this.runTranscoding(video, 'webtorrent'), handler: ({ video }) => this.runTranscoding(video, 'web-video'),
isDisplayed: () => this.displayOptions.transcoding && this.canRunTranscoding(), isDisplayed: () => this.displayOptions.transcoding && this.canRunTranscoding(),
iconName: 'cog' iconName: 'cog'
}, },
@ -406,8 +406,8 @@ export class VideoActionsDropdownComponent implements OnChanges {
iconName: 'delete' iconName: 'delete'
}, },
{ {
label: $localize`Delete WebTorrent files`, label: $localize`Delete Web Video files`,
handler: ({ video }) => this.removeVideoFiles(video, 'webtorrent'), handler: ({ video }) => this.removeVideoFiles(video, 'web-videos'),
isDisplayed: () => this.displayOptions.removeFiles && this.canRemoveVideoFiles(), isDisplayed: () => this.displayOptions.removeFiles && this.canRemoveVideoFiles(),
iconName: 'delete' iconName: 'delete'
} }

View File

@ -201,7 +201,7 @@ object_storage:
# Useful when you want to use a CDN/external proxy # Useful when you want to use a CDN/external proxy
base_url: '' # Example: 'https://mirror.example.com' base_url: '' # Example: 'https://mirror.example.com'
# Same settings but for webtorrent videos # Same settings but for web videos
videos: videos:
bucket_name: 'videos' bucket_name: 'videos'
prefix: '' prefix: ''
@ -480,18 +480,18 @@ transcoding:
# Transcode and keep original resolution, even if it's above your maximum enabled resolution # Transcode and keep original resolution, even if it's above your maximum enabled resolution
always_transcode_original_resolution: true always_transcode_original_resolution: true
# Generate videos in a WebTorrent format (what we do since the first PeerTube release) # Generate videos in a web compatible format
# If you also enabled the hls format, it will multiply videos storage by 2 # If you also enabled the hls format, it will multiply videos storage by 2
# If disabled, breaks federation with PeerTube instances < 2.1 # If disabled, breaks federation with PeerTube instances < 2.1
webtorrent: webtorrent:
enabled: false enabled: false
# /!\ Requires ffmpeg >= 4.1 # /!\ Requires ffmpeg >= 4.1
# Generate HLS playlists and fragmented MP4 files. Better playback than with WebTorrent: # Generate HLS playlists and fragmented MP4 files. Better playback than with Web Videos:
# * Resolution change is smoother # * Resolution change is smoother
# * Faster playback in particular with long videos # * Faster playback in particular with long videos
# * More stable playback (less bugs/infinite loading) # * More stable playback (less bugs/infinite loading)
# If you also enabled the webtorrent format, it will multiply videos storage by 2 # If you also enabled the web videos format, it will multiply videos storage by 2
hls: hls:
enabled: true enabled: true

View File

@ -199,7 +199,7 @@ object_storage:
# Useful when you want to use a CDN/external proxy # Useful when you want to use a CDN/external proxy
base_url: '' # Example: 'https://mirror.example.com' base_url: '' # Example: 'https://mirror.example.com'
# Same settings but for webtorrent videos # Same settings but for web videos
videos: videos:
bucket_name: 'videos' bucket_name: 'videos'
prefix: '' prefix: ''
@ -490,18 +490,18 @@ transcoding:
# Transcode and keep original resolution, even if it's above your maximum enabled resolution # Transcode and keep original resolution, even if it's above your maximum enabled resolution
always_transcode_original_resolution: true always_transcode_original_resolution: true
# Generate videos in a WebTorrent format (what we do since the first PeerTube release) # Generate videos in a web compatible format
# If you also enabled the hls format, it will multiply videos storage by 2 # If you also enabled the hls format, it will multiply videos storage by 2
# If disabled, breaks federation with PeerTube instances < 2.1 # If disabled, breaks federation with PeerTube instances < 2.1
webtorrent: webtorrent:
enabled: false enabled: false
# /!\ Requires ffmpeg >= 4.1 # /!\ Requires ffmpeg >= 4.1
# Generate HLS playlists and fragmented MP4 files. Better playback than with WebTorrent: # Generate HLS playlists and fragmented MP4 files. Better playback than with Web Videos:
# * Resolution change is smoother # * Resolution change is smoother
# * Faster playback in particular with long videos # * Faster playback in particular with long videos
# * More stable playback (less bugs/infinite loading) # * More stable playback (less bugs/infinite loading)
# If you also enabled the webtorrent format, it will multiply videos storage by 2 # If you also enabled the web videos format, it will multiply videos storage by 2
hls: hls:
enabled: true enabled: true
@ -599,7 +599,6 @@ video_studio:
# If enabled, users can create transcoding tasks as they wish # If enabled, users can create transcoding tasks as they wish
enabled: false enabled: false
# Enable remote runners to transcode studio tasks # Enable remote runners to transcode studio tasks
# If enabled, your instance won't transcode the videos itself # If enabled, your instance won't transcode the videos itself
# At least 1 remote runner must be configured to transcode your videos # At least 1 remote runner must be configured to transcode your videos

View File

@ -37,8 +37,8 @@ async function run () {
console.log('Detecting files to remove, it could take a while...') console.log('Detecting files to remove, it could take a while...')
toDelete = toDelete.concat( toDelete = toDelete.concat(
await pruneDirectory(DIRECTORIES.VIDEOS.PUBLIC, doesWebTorrentFileExist()), await pruneDirectory(DIRECTORIES.VIDEOS.PUBLIC, doesWebVideoFileExist()),
await pruneDirectory(DIRECTORIES.VIDEOS.PRIVATE, doesWebTorrentFileExist()), await pruneDirectory(DIRECTORIES.VIDEOS.PRIVATE, doesWebVideoFileExist()),
await pruneDirectory(DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE, doesHLSPlaylistExist()), await pruneDirectory(DIRECTORIES.HLS_STREAMING_PLAYLIST.PRIVATE, doesHLSPlaylistExist()),
await pruneDirectory(DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC, doesHLSPlaylistExist()), await pruneDirectory(DIRECTORIES.HLS_STREAMING_PLAYLIST.PUBLIC, doesHLSPlaylistExist()),
@ -93,12 +93,12 @@ async function pruneDirectory (directory: string, existFun: ExistFun) {
return toDelete return toDelete
} }
function doesWebTorrentFileExist () { function doesWebVideoFileExist () {
return (filePath: string) => { return (filePath: string) => {
// Don't delete private directory // Don't delete private directory
if (filePath === DIRECTORIES.VIDEOS.PRIVATE) return true if (filePath === DIRECTORIES.VIDEOS.PRIVATE) return true
return VideoFileModel.doesOwnedWebTorrentVideoFileExist(basename(filePath)) return VideoFileModel.doesOwnedWebVideoFileExist(basename(filePath))
} }
} }

View File

@ -1,6 +1,6 @@
import express from 'express' import express from 'express'
import { logger, loggerTagsFactory } from '@server/helpers/logger' import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { proxifyHLS, proxifyWebTorrentFile } from '@server/lib/object-storage' import { proxifyHLS, proxifyWebVideoFile } from '@server/lib/object-storage'
import { VideoPathManager } from '@server/lib/video-path-manager' import { VideoPathManager } from '@server/lib/video-path-manager'
import { getStudioTaskFilePath } from '@server/lib/video-studio' import { getStudioTaskFilePath } from '@server/lib/video-studio'
import { apiRateLimiter, asyncMiddleware } from '@server/middlewares' import { apiRateLimiter, asyncMiddleware } from '@server/middlewares'
@ -70,7 +70,7 @@ async function getMaxQualityVideoFile (req: express.Request, res: express.Respon
} }
// Web video // Web video
return proxifyWebTorrentFile({ return proxifyWebVideoFile({
req, req,
res, res,
filename: file.filename filename: file.filename

View File

@ -213,19 +213,14 @@ async function updateMe (req: express.Request, res: express.Response) {
'noInstanceConfigWarningModal', 'noInstanceConfigWarningModal',
'noAccountSetupWarningModal', 'noAccountSetupWarningModal',
'noWelcomeModal', 'noWelcomeModal',
'emailPublic' 'emailPublic',
'p2pEnabled'
] ]
for (const key of keysToUpdate) { for (const key of keysToUpdate) {
if (body[key] !== undefined) user.set(key, body[key]) if (body[key] !== undefined) user.set(key, body[key])
} }
if (body.p2pEnabled !== undefined) {
user.set('p2pEnabled', body.p2pEnabled)
} else if (body.webTorrentEnabled !== undefined) { // FIXME: deprecated in 4.1
user.set('p2pEnabled', body.webTorrentEnabled)
}
if (body.email !== undefined) { if (body.email !== undefined) {
if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) { if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION) {
user.pendingEmail = body.email user.pendingEmail = body.email

View File

@ -2,7 +2,8 @@ import express from 'express'
import toInt from 'validator/lib/toInt' import toInt from 'validator/lib/toInt'
import { logger, loggerTagsFactory } from '@server/helpers/logger' import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { federateVideoIfNeeded } from '@server/lib/activitypub/videos' import { federateVideoIfNeeded } from '@server/lib/activitypub/videos'
import { removeAllWebTorrentFiles, removeHLSFile, removeHLSPlaylist, removeWebTorrentFile } from '@server/lib/video-file' import { updatePlaylistAfterFileChange } from '@server/lib/hls'
import { removeAllWebVideoFiles, removeHLSFile, removeHLSPlaylist, removeWebVideoFile } from '@server/lib/video-file'
import { VideoFileModel } from '@server/models/video/video-file' import { VideoFileModel } from '@server/models/video/video-file'
import { HttpStatusCode, UserRight } from '@shared/models' import { HttpStatusCode, UserRight } from '@shared/models'
import { import {
@ -12,11 +13,10 @@ import {
videoFileMetadataGetValidator, videoFileMetadataGetValidator,
videoFilesDeleteHLSFileValidator, videoFilesDeleteHLSFileValidator,
videoFilesDeleteHLSValidator, videoFilesDeleteHLSValidator,
videoFilesDeleteWebTorrentFileValidator, videoFilesDeleteWebVideoFileValidator,
videoFilesDeleteWebTorrentValidator, videoFilesDeleteWebVideoValidator,
videosGetValidator videosGetValidator
} from '../../../middlewares' } from '../../../middlewares'
import { updatePlaylistAfterFileChange } from '@server/lib/hls'
const lTags = loggerTagsFactory('api', 'video') const lTags = loggerTagsFactory('api', 'video')
const filesRouter = express.Router() const filesRouter = express.Router()
@ -40,17 +40,19 @@ filesRouter.delete('/:id/hls/:videoFileId',
asyncMiddleware(removeHLSFileController) asyncMiddleware(removeHLSFileController)
) )
filesRouter.delete('/:id/webtorrent', filesRouter.delete(
[ '/:id/webtorrent', '/:id/web-videos' ], // TODO: remove webtorrent in V7
authenticate, authenticate,
ensureUserHasRight(UserRight.MANAGE_VIDEO_FILES), ensureUserHasRight(UserRight.MANAGE_VIDEO_FILES),
asyncMiddleware(videoFilesDeleteWebTorrentValidator), asyncMiddleware(videoFilesDeleteWebVideoValidator),
asyncMiddleware(removeAllWebTorrentFilesController) asyncMiddleware(removeAllWebVideoFilesController)
) )
filesRouter.delete('/:id/webtorrent/:videoFileId', filesRouter.delete(
[ '/:id/webtorrent/:videoFileId', '/:id/web-videos/:videoFileId' ], // TODO: remove webtorrent in V7
authenticate, authenticate,
ensureUserHasRight(UserRight.MANAGE_VIDEO_FILES), ensureUserHasRight(UserRight.MANAGE_VIDEO_FILES),
asyncMiddleware(videoFilesDeleteWebTorrentFileValidator), asyncMiddleware(videoFilesDeleteWebVideoFileValidator),
asyncMiddleware(removeWebTorrentFileController) asyncMiddleware(removeWebVideoFileController)
) )
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -96,24 +98,24 @@ async function removeHLSFileController (req: express.Request, res: express.Respo
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function removeAllWebTorrentFilesController (req: express.Request, res: express.Response) { async function removeAllWebVideoFilesController (req: express.Request, res: express.Response) {
const video = res.locals.videoAll const video = res.locals.videoAll
logger.info('Deleting WebTorrent files of %s.', video.url, lTags(video.uuid)) logger.info('Deleting Web Video files of %s.', video.url, lTags(video.uuid))
await removeAllWebTorrentFiles(video) await removeAllWebVideoFiles(video)
await federateVideoIfNeeded(video, false, undefined) await federateVideoIfNeeded(video, false, undefined)
return res.sendStatus(HttpStatusCode.NO_CONTENT_204) return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
} }
async function removeWebTorrentFileController (req: express.Request, res: express.Response) { async function removeWebVideoFileController (req: express.Request, res: express.Response) {
const video = res.locals.videoAll const video = res.locals.videoAll
const videoFileId = +req.params.videoFileId const videoFileId = +req.params.videoFileId
logger.info('Deleting WebTorrent file %d of %s.', videoFileId, video.url, lTags(video.uuid)) logger.info('Deleting Web Video file %d of %s.', videoFileId, video.url, lTags(video.uuid))
await removeWebTorrentFile(video, videoFileId) await removeWebVideoFile(video, videoFileId)
await federateVideoIfNeeded(video, false, undefined) await federateVideoIfNeeded(video, false, undefined)
return res.sendStatus(HttpStatusCode.NO_CONTENT_204) return res.sendStatus(HttpStatusCode.NO_CONTENT_204)

View File

@ -1,11 +1,11 @@
import cors from 'cors' import cors from 'cors'
import express from 'express' import express from 'express'
import { OBJECT_STORAGE_PROXY_PATHS } from '@server/initializers/constants' import { OBJECT_STORAGE_PROXY_PATHS } from '@server/initializers/constants'
import { proxifyHLS, proxifyWebTorrentFile } from '@server/lib/object-storage' import { proxifyHLS, proxifyWebVideoFile } from '@server/lib/object-storage'
import { import {
asyncMiddleware, asyncMiddleware,
ensureCanAccessPrivateVideoHLSFiles, ensureCanAccessPrivateVideoHLSFiles,
ensureCanAccessVideoPrivateWebTorrentFiles, ensureCanAccessVideoPrivateWebVideoFiles,
ensurePrivateObjectStorageProxyIsEnabled, ensurePrivateObjectStorageProxyIsEnabled,
optionalAuthenticate optionalAuthenticate
} from '@server/middlewares' } from '@server/middlewares'
@ -18,8 +18,8 @@ objectStorageProxyRouter.use(cors())
objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + ':filename', objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + ':filename',
ensurePrivateObjectStorageProxyIsEnabled, ensurePrivateObjectStorageProxyIsEnabled,
optionalAuthenticate, optionalAuthenticate,
asyncMiddleware(ensureCanAccessVideoPrivateWebTorrentFiles), asyncMiddleware(ensureCanAccessVideoPrivateWebVideoFiles),
asyncMiddleware(proxifyWebTorrentController) asyncMiddleware(proxifyWebVideoController)
) )
objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:filename', objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:filename',
@ -35,10 +35,10 @@ export {
objectStorageProxyRouter objectStorageProxyRouter
} }
function proxifyWebTorrentController (req: express.Request, res: express.Response) { function proxifyWebVideoController (req: express.Request, res: express.Response) {
const filename = req.params.filename const filename = req.params.filename
return proxifyWebTorrentFile({ req, res, filename }) return proxifyWebVideoFile({ req, res, filename })
} }
function proxifyHLSController (req: express.Request, res: express.Response) { function proxifyHLSController (req: express.Request, res: express.Response) {

View File

@ -6,7 +6,7 @@ import { injectQueryToPlaylistUrls } from '@server/lib/hls'
import { import {
asyncMiddleware, asyncMiddleware,
ensureCanAccessPrivateVideoHLSFiles, ensureCanAccessPrivateVideoHLSFiles,
ensureCanAccessVideoPrivateWebTorrentFiles, ensureCanAccessVideoPrivateWebVideoFiles,
handleStaticError, handleStaticError,
optionalAuthenticate optionalAuthenticate
} from '@server/middlewares' } from '@server/middlewares'
@ -21,16 +21,16 @@ const staticRouter = express.Router()
staticRouter.use(cors()) staticRouter.use(cors())
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// WebTorrent/Classic videos // Web videos/Classic videos
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const privateWebTorrentStaticMiddlewares = CONFIG.STATIC_FILES.PRIVATE_FILES_REQUIRE_AUTH === true const privateWebVideoStaticMiddlewares = CONFIG.STATIC_FILES.PRIVATE_FILES_REQUIRE_AUTH === true
? [ optionalAuthenticate, asyncMiddleware(ensureCanAccessVideoPrivateWebTorrentFiles) ] ? [ optionalAuthenticate, asyncMiddleware(ensureCanAccessVideoPrivateWebVideoFiles) ]
: [] : []
staticRouter.use( staticRouter.use(
STATIC_PATHS.PRIVATE_WEBSEED, STATIC_PATHS.PRIVATE_WEBSEED,
...privateWebTorrentStaticMiddlewares, ...privateWebVideoStaticMiddlewares,
express.static(DIRECTORIES.VIDEOS.PRIVATE, { fallthrough: false }), express.static(DIRECTORIES.VIDEOS.PRIVATE, { fallthrough: false }),
handleStaticError handleStaticError
) )

View File

@ -1,5 +1,6 @@
function isValidPlayerMode (value: any) { function isValidPlayerMode (value: any) {
return value === 'webtorrent' || value === 'p2p-media-loader' // TODO: remove webtorrent in v7
return value === 'webtorrent' || value === 'web-video' || value === 'p2p-media-loader'
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -2,7 +2,7 @@ import { exists } from './misc'
function isValidCreateTranscodingType (value: any) { function isValidCreateTranscodingType (value: any) {
return exists(value) && return exists(value) &&
(value === 'hls' || value === 'webtorrent') (value === 'hls' || value === 'webtorrent' || value === 'web-video') // TODO: remove webtorrent in v7
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -23,7 +23,8 @@ function pickCommonVideoQuery (query: VideosCommonQueryAfterSanitize) {
'include', 'include',
'skipCount', 'skipCount',
'hasHLSFiles', 'hasHLSFiles',
'hasWebtorrentFiles', 'hasWebtorrentFiles', // TODO: Remove in v7
'hasWebVideoFiles',
'search', 'search',
'excludeAlreadyWatched' 'excludeAlreadyWatched'
]) ])

View File

@ -199,7 +199,7 @@ function checkStorageConfig () {
function checkTranscodingConfig () { function checkTranscodingConfig () {
if (CONFIG.TRANSCODING.ENABLED) { if (CONFIG.TRANSCODING.ENABLED) {
if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false && CONFIG.TRANSCODING.HLS.ENABLED === false) { if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false && CONFIG.TRANSCODING.HLS.ENABLED === false) {
throw new Error('You need to enable at least WebTorrent transcoding or HLS transcoding.') throw new Error('You need to enable at least Web Video transcoding or HLS transcoding.')
} }
if (CONFIG.TRANSCODING.CONCURRENCY <= 0) { if (CONFIG.TRANSCODING.CONCURRENCY <= 0) {

View File

@ -126,7 +126,7 @@ export abstract class APVideoAbstractBuilder {
video.VideoLive = videoLive video.VideoLive = videoLive
} }
protected async setWebTorrentFiles (video: MVideoFullLight, t: Transaction) { protected async setWebVideoFiles (video: MVideoFullLight, t: Transaction) {
const videoFileAttributes = getFileAttributesFromUrl(video, this.videoObject.url) const videoFileAttributes = getFileAttributesFromUrl(video, this.videoObject.url)
const newVideoFiles = videoFileAttributes.map(a => new VideoFileModel(a)) const newVideoFiles = videoFileAttributes.map(a => new VideoFileModel(a))

View File

@ -33,7 +33,7 @@ export class APVideoCreator extends APVideoAbstractBuilder {
await this.setThumbnail(videoCreated, t) await this.setThumbnail(videoCreated, t)
await this.setPreview(videoCreated, t) await this.setPreview(videoCreated, t)
await this.setWebTorrentFiles(videoCreated, t) await this.setWebVideoFiles(videoCreated, t)
await this.setStreamingPlaylists(videoCreated, t) await this.setStreamingPlaylists(videoCreated, t)
await this.setTags(videoCreated, t) await this.setTags(videoCreated, t)
await this.setTrackers(videoCreated, t) await this.setTrackers(videoCreated, t)

View File

@ -50,7 +50,7 @@ export class APVideoUpdater extends APVideoAbstractBuilder {
if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel) if (thumbnailModel) await videoUpdated.addAndSaveThumbnail(thumbnailModel)
await runInReadCommittedTransaction(async t => { await runInReadCommittedTransaction(async t => {
await this.setWebTorrentFiles(videoUpdated, t) await this.setWebVideoFiles(videoUpdated, t)
await this.setStreamingPlaylists(videoUpdated, t) await this.setStreamingPlaylists(videoUpdated, t)
}) })

View File

@ -4,7 +4,7 @@ import { join } from 'path'
import { logger, loggerTagsFactory } from '@server/helpers/logger' import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { updateTorrentMetadata } from '@server/helpers/webtorrent' import { updateTorrentMetadata } from '@server/helpers/webtorrent'
import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants' import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants'
import { storeHLSFileFromFilename, storeWebTorrentFile } from '@server/lib/object-storage' import { storeHLSFileFromFilename, storeWebVideoFile } from '@server/lib/object-storage'
import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths' import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths'
import { VideoPathManager } from '@server/lib/video-path-manager' import { VideoPathManager } from '@server/lib/video-path-manager'
import { moveToFailedMoveToObjectStorageState, moveToNextState } from '@server/lib/video-state' import { moveToFailedMoveToObjectStorageState, moveToNextState } from '@server/lib/video-state'
@ -33,9 +33,9 @@ export async function processMoveToObjectStorage (job: Job) {
try { try {
if (video.VideoFiles) { if (video.VideoFiles) {
logger.debug('Moving %d webtorrent files for video %s.', video.VideoFiles.length, video.uuid, lTags) logger.debug('Moving %d web video files for video %s.', video.VideoFiles.length, video.uuid, lTags)
await moveWebTorrentFiles(video) await moveWebVideoFiles(video)
} }
if (video.VideoStreamingPlaylists) { if (video.VideoStreamingPlaylists) {
@ -75,11 +75,11 @@ export async function onMoveToObjectStorageFailure (job: Job, err: any) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function moveWebTorrentFiles (video: MVideoWithAllFiles) { async function moveWebVideoFiles (video: MVideoWithAllFiles) {
for (const file of video.VideoFiles) { for (const file of video.VideoFiles) {
if (file.storage !== VideoStorage.FILE_SYSTEM) continue if (file.storage !== VideoStorage.FILE_SYSTEM) continue
const fileUrl = await storeWebTorrentFile(video, file) const fileUrl = await storeWebVideoFile(video, file)
const oldPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, file) const oldPath = VideoPathManager.Instance.getFSVideoFileOutputPath(video, file)
await onFileMoved({ videoOrPlaylist: video, file, fileUrl, oldPath }) await onFileMoved({ videoOrPlaylist: video, file, fileUrl, oldPath })

View File

@ -3,7 +3,7 @@ import { copy, stat } from 'fs-extra'
import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
import { CONFIG } from '@server/initializers/config' import { CONFIG } from '@server/initializers/config'
import { federateVideoIfNeeded } from '@server/lib/activitypub/videos' import { federateVideoIfNeeded } from '@server/lib/activitypub/videos'
import { generateWebTorrentVideoFilename } from '@server/lib/paths' import { generateWebVideoFilename } from '@server/lib/paths'
import { buildMoveToObjectStorageJob } from '@server/lib/video' import { buildMoveToObjectStorageJob } from '@server/lib/video'
import { VideoPathManager } from '@server/lib/video-path-manager' import { VideoPathManager } from '@server/lib/video-path-manager'
import { VideoModel } from '@server/models/video/video' import { VideoModel } from '@server/models/video/video'
@ -56,7 +56,7 @@ async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) {
if (currentVideoFile) { if (currentVideoFile) {
// Remove old file and old torrent // Remove old file and old torrent
await video.removeWebTorrentFile(currentVideoFile) await video.removeWebVideoFile(currentVideoFile)
// Remove the old video file from the array // Remove the old video file from the array
video.VideoFiles = video.VideoFiles.filter(f => f !== currentVideoFile) video.VideoFiles = video.VideoFiles.filter(f => f !== currentVideoFile)
@ -66,7 +66,7 @@ async function updateVideoFile (video: MVideoFullLight, inputFilePath: string) {
const newVideoFile = new VideoFileModel({ const newVideoFile = new VideoFileModel({
resolution, resolution,
extname: fileExt, extname: fileExt,
filename: generateWebTorrentVideoFilename(resolution, fileExt), filename: generateWebVideoFilename(resolution, fileExt),
storage: VideoStorage.FILE_SYSTEM, storage: VideoStorage.FILE_SYSTEM,
size, size,
fps, fps,

View File

@ -4,7 +4,7 @@ import { retryTransactionWrapper } from '@server/helpers/database-utils'
import { YoutubeDLWrapper } from '@server/helpers/youtube-dl' import { YoutubeDLWrapper } from '@server/helpers/youtube-dl'
import { CONFIG } from '@server/initializers/config' import { CONFIG } from '@server/initializers/config'
import { isPostImportVideoAccepted } from '@server/lib/moderation' import { isPostImportVideoAccepted } from '@server/lib/moderation'
import { generateWebTorrentVideoFilename } from '@server/lib/paths' import { generateWebVideoFilename } from '@server/lib/paths'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
import { ServerConfigManager } from '@server/lib/server-config-manager' import { ServerConfigManager } from '@server/lib/server-config-manager'
import { createOptimizeOrMergeAudioJobs } from '@server/lib/transcoding/create-transcoding-job' import { createOptimizeOrMergeAudioJobs } from '@server/lib/transcoding/create-transcoding-job'
@ -148,7 +148,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid
extname: fileExt, extname: fileExt,
resolution, resolution,
size: stats.size, size: stats.size,
filename: generateWebTorrentVideoFilename(resolution, fileExt), filename: generateWebVideoFilename(resolution, fileExt),
fps, fps,
videoId: videoImport.videoId videoId: videoImport.videoId
} }

View File

@ -1,8 +1,8 @@
import { Job } from 'bullmq' import { Job } from 'bullmq'
import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding' import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding'
import { generateHlsPlaylistResolution } from '@server/lib/transcoding/hls-transcoding' import { generateHlsPlaylistResolution } from '@server/lib/transcoding/hls-transcoding'
import { mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewWebTorrentResolution } from '@server/lib/transcoding/web-transcoding' import { mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewWebVideoResolution } from '@server/lib/transcoding/web-transcoding'
import { removeAllWebTorrentFiles } from '@server/lib/video-file' import { removeAllWebVideoFiles } from '@server/lib/video-file'
import { VideoPathManager } from '@server/lib/video-path-manager' import { VideoPathManager } from '@server/lib/video-path-manager'
import { moveToFailedTranscodingState } from '@server/lib/video-state' import { moveToFailedTranscodingState } from '@server/lib/video-state'
import { UserModel } from '@server/models/user/user' import { UserModel } from '@server/models/user/user'
@ -11,7 +11,7 @@ import { MUser, MUserId, MVideoFullLight } from '@server/types/models'
import { import {
HLSTranscodingPayload, HLSTranscodingPayload,
MergeAudioTranscodingPayload, MergeAudioTranscodingPayload,
NewWebTorrentResolutionTranscodingPayload, NewWebVideoResolutionTranscodingPayload,
OptimizeTranscodingPayload, OptimizeTranscodingPayload,
VideoTranscodingPayload VideoTranscodingPayload
} from '@shared/models' } from '@shared/models'
@ -22,9 +22,9 @@ type HandlerFunction = (job: Job, payload: VideoTranscodingPayload, video: MVide
const handlers: { [ id in VideoTranscodingPayload['type'] ]: HandlerFunction } = { const handlers: { [ id in VideoTranscodingPayload['type'] ]: HandlerFunction } = {
'new-resolution-to-hls': handleHLSJob, 'new-resolution-to-hls': handleHLSJob,
'new-resolution-to-webtorrent': handleNewWebTorrentResolutionJob, 'new-resolution-to-web-video': handleNewWebVideoResolutionJob,
'merge-audio-to-webtorrent': handleWebTorrentMergeAudioJob, 'merge-audio-to-web-video': handleWebVideoMergeAudioJob,
'optimize-to-webtorrent': handleWebTorrentOptimizeJob 'optimize-to-web-video': handleWebVideoOptimizeJob
} }
const lTags = loggerTagsFactory('transcoding') const lTags = loggerTagsFactory('transcoding')
@ -74,7 +74,7 @@ export {
// Job handlers // Job handlers
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function handleWebTorrentMergeAudioJob (job: Job, payload: MergeAudioTranscodingPayload, video: MVideoFullLight, user: MUserId) { async function handleWebVideoMergeAudioJob (job: Job, payload: MergeAudioTranscodingPayload, video: MVideoFullLight, user: MUserId) {
logger.info('Handling merge audio transcoding job for %s.', video.uuid, lTags(video.uuid), { payload }) logger.info('Handling merge audio transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
await mergeAudioVideofile({ video, resolution: payload.resolution, fps: payload.fps, job }) await mergeAudioVideofile({ video, resolution: payload.resolution, fps: payload.fps, job })
@ -84,7 +84,7 @@ async function handleWebTorrentMergeAudioJob (job: Job, payload: MergeAudioTrans
await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: !payload.hasChildren, video }) await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: !payload.hasChildren, video })
} }
async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) { async function handleWebVideoOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
logger.info('Handling optimize transcoding job for %s.', video.uuid, lTags(video.uuid), { payload }) logger.info('Handling optimize transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
await optimizeOriginalVideofile({ video, inputVideoFile: video.getMaxQualityFile(), quickTranscode: payload.quickTranscode, job }) await optimizeOriginalVideofile({ video, inputVideoFile: video.getMaxQualityFile(), quickTranscode: payload.quickTranscode, job })
@ -96,12 +96,12 @@ async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodi
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function handleNewWebTorrentResolutionJob (job: Job, payload: NewWebTorrentResolutionTranscodingPayload, video: MVideoFullLight) { async function handleNewWebVideoResolutionJob (job: Job, payload: NewWebVideoResolutionTranscodingPayload, video: MVideoFullLight) {
logger.info('Handling WebTorrent transcoding job for %s.', video.uuid, lTags(video.uuid), { payload }) logger.info('Handling Web Video transcoding job for %s.', video.uuid, lTags(video.uuid), { payload })
await transcodeNewWebTorrentResolution({ video, resolution: payload.resolution, fps: payload.fps, job }) await transcodeNewWebVideoResolution({ video, resolution: payload.resolution, fps: payload.fps, job })
logger.info('WebTorrent transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload }) logger.info('Web Video transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: true, video }) await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: true, video })
} }
@ -118,7 +118,7 @@ async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, videoArg:
video = await VideoModel.loadFull(videoArg.uuid) video = await VideoModel.loadFull(videoArg.uuid)
const videoFileInput = payload.copyCodecs const videoFileInput = payload.copyCodecs
? video.getWebTorrentFile(payload.resolution) ? video.getWebVideoFile(payload.resolution)
: video.getMaxQualityFile() : video.getMaxQualityFile()
const videoOrStreamingPlaylist = videoFileInput.getVideoOrStreamingPlaylist() const videoOrStreamingPlaylist = videoFileInput.getVideoOrStreamingPlaylist()
@ -140,10 +140,10 @@ async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, videoArg:
logger.info('HLS transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload }) logger.info('HLS transcoding job for %s ended.', video.uuid, lTags(video.uuid), { payload })
if (payload.deleteWebTorrentFiles === true) { if (payload.deleteWebVideoFiles === true) {
logger.info('Removing WebTorrent files of %s now we have a HLS version of it.', video.uuid, lTags(video.uuid)) logger.info('Removing Web Video files of %s now we have a HLS version of it.', video.uuid, lTags(video.uuid))
await removeAllWebTorrentFiles(video) await removeAllWebVideoFiles(video)
} }
await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: true, video }) await onTranscodingEnded({ isNewVideo: payload.isNewVideo, moveVideoToNextState: true, video })

View File

@ -9,12 +9,12 @@ function generateHLSObjectBaseStorageKey (playlist: MStreamingPlaylistVideo) {
return join(playlist.getStringType(), playlist.Video.uuid) return join(playlist.getStringType(), playlist.Video.uuid)
} }
function generateWebTorrentObjectStorageKey (filename: string) { function generateWebVideoObjectStorageKey (filename: string) {
return filename return filename
} }
export { export {
generateHLSObjectStorageKey, generateHLSObjectStorageKey,
generateHLSObjectBaseStorageKey, generateHLSObjectBaseStorageKey,
generateWebTorrentObjectStorageKey generateWebVideoObjectStorageKey
} }

View File

@ -2,9 +2,9 @@ import { GetObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner' import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
import { CONFIG } from '@server/initializers/config' import { CONFIG } from '@server/initializers/config'
import { MStreamingPlaylistVideo, MVideoFile } from '@server/types/models' import { MStreamingPlaylistVideo, MVideoFile } from '@server/types/models'
import { generateHLSObjectStorageKey, generateWebTorrentObjectStorageKey } from './keys' import { generateHLSObjectStorageKey, generateWebVideoObjectStorageKey } from './keys'
import { buildKey, getClient } from './shared' import { buildKey, getClient } from './shared'
import { getHLSPublicFileUrl, getWebTorrentPublicFileUrl } from './urls' import { getHLSPublicFileUrl, getWebVideoPublicFileUrl } from './urls'
export async function generateWebVideoPresignedUrl (options: { export async function generateWebVideoPresignedUrl (options: {
file: MVideoFile file: MVideoFile
@ -12,7 +12,7 @@ export async function generateWebVideoPresignedUrl (options: {
}) { }) {
const { file, downloadFilename } = options const { file, downloadFilename } = options
const key = generateWebTorrentObjectStorageKey(file.filename) const key = generateWebVideoObjectStorageKey(file.filename)
const command = new GetObjectCommand({ const command = new GetObjectCommand({
Bucket: CONFIG.OBJECT_STORAGE.VIDEOS.BUCKET_NAME, Bucket: CONFIG.OBJECT_STORAGE.VIDEOS.BUCKET_NAME,
@ -22,7 +22,7 @@ export async function generateWebVideoPresignedUrl (options: {
const url = await getSignedUrl(getClient(), command, { expiresIn: 3600 * 24 }) const url = await getSignedUrl(getClient(), command, { expiresIn: 3600 * 24 })
return getWebTorrentPublicFileUrl(url) return getWebVideoPublicFileUrl(url)
} }
export async function generateHLSFilePresignedUrl (options: { export async function generateHLSFilePresignedUrl (options: {

View File

@ -7,19 +7,19 @@ import { StreamReplacer } from '@server/helpers/stream-replacer'
import { MStreamingPlaylist, MVideo } from '@server/types/models' import { MStreamingPlaylist, MVideo } from '@server/types/models'
import { HttpStatusCode } from '@shared/models' import { HttpStatusCode } from '@shared/models'
import { injectQueryToPlaylistUrls } from '../hls' import { injectQueryToPlaylistUrls } from '../hls'
import { getHLSFileReadStream, getWebTorrentFileReadStream } from './videos' import { getHLSFileReadStream, getWebVideoFileReadStream } from './videos'
export async function proxifyWebTorrentFile (options: { export async function proxifyWebVideoFile (options: {
req: express.Request req: express.Request
res: express.Response res: express.Response
filename: string filename: string
}) { }) {
const { req, res, filename } = options const { req, res, filename } = options
logger.debug('Proxifying WebTorrent file %s from object storage.', filename) logger.debug('Proxifying Web Video file %s from object storage.', filename)
try { try {
const { response: s3Response, stream } = await getWebTorrentFileReadStream({ const { response: s3Response, stream } = await getWebVideoFileReadStream({
filename, filename,
rangeHeader: req.header('range') rangeHeader: req.header('range')
}) })

View File

@ -9,7 +9,7 @@ function getInternalUrl (config: BucketInfo, keyWithoutPrefix: string) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function getWebTorrentPublicFileUrl (fileUrl: string) { function getWebVideoPublicFileUrl (fileUrl: string) {
const baseUrl = CONFIG.OBJECT_STORAGE.VIDEOS.BASE_URL const baseUrl = CONFIG.OBJECT_STORAGE.VIDEOS.BASE_URL
if (!baseUrl) return fileUrl if (!baseUrl) return fileUrl
@ -29,7 +29,7 @@ function getHLSPrivateFileUrl (video: MVideoUUID, filename: string) {
return WEBSERVER.URL + OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + video.uuid + `/${filename}` return WEBSERVER.URL + OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + video.uuid + `/${filename}`
} }
function getWebTorrentPrivateFileUrl (filename: string) { function getWebVideoPrivateFileUrl (filename: string) {
return WEBSERVER.URL + OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + filename return WEBSERVER.URL + OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + filename
} }
@ -38,11 +38,11 @@ function getWebTorrentPrivateFileUrl (filename: string) {
export { export {
getInternalUrl, getInternalUrl,
getWebTorrentPublicFileUrl, getWebVideoPublicFileUrl,
getHLSPublicFileUrl, getHLSPublicFileUrl,
getHLSPrivateFileUrl, getHLSPrivateFileUrl,
getWebTorrentPrivateFileUrl, getWebVideoPrivateFileUrl,
replaceByBaseUrl replaceByBaseUrl
} }

View File

@ -4,7 +4,7 @@ import { CONFIG } from '@server/initializers/config'
import { MStreamingPlaylistVideo, MVideo, MVideoFile } from '@server/types/models' import { MStreamingPlaylistVideo, MVideo, MVideoFile } from '@server/types/models'
import { getHLSDirectory } from '../paths' import { getHLSDirectory } from '../paths'
import { VideoPathManager } from '../video-path-manager' import { VideoPathManager } from '../video-path-manager'
import { generateHLSObjectBaseStorageKey, generateHLSObjectStorageKey, generateWebTorrentObjectStorageKey } from './keys' import { generateHLSObjectBaseStorageKey, generateHLSObjectStorageKey, generateWebVideoObjectStorageKey } from './keys'
import { import {
createObjectReadStream, createObjectReadStream,
listKeysOfPrefix, listKeysOfPrefix,
@ -55,10 +55,10 @@ function storeHLSFileFromContent (playlist: MStreamingPlaylistVideo, path: strin
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function storeWebTorrentFile (video: MVideo, file: MVideoFile) { function storeWebVideoFile (video: MVideo, file: MVideoFile) {
return storeObject({ return storeObject({
inputPath: VideoPathManager.Instance.getFSVideoFileOutputPath(video, file), inputPath: VideoPathManager.Instance.getFSVideoFileOutputPath(video, file),
objectStorageKey: generateWebTorrentObjectStorageKey(file.filename), objectStorageKey: generateWebVideoObjectStorageKey(file.filename),
bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS, bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS,
isPrivate: video.hasPrivateStaticPath() isPrivate: video.hasPrivateStaticPath()
}) })
@ -66,9 +66,9 @@ function storeWebTorrentFile (video: MVideo, file: MVideoFile) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function updateWebTorrentFileACL (video: MVideo, file: MVideoFile) { async function updateWebVideoFileACL (video: MVideo, file: MVideoFile) {
await updateObjectACL({ await updateObjectACL({
objectStorageKey: generateWebTorrentObjectStorageKey(file.filename), objectStorageKey: generateWebVideoObjectStorageKey(file.filename),
bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS, bucketInfo: CONFIG.OBJECT_STORAGE.VIDEOS,
isPrivate: video.hasPrivateStaticPath() isPrivate: video.hasPrivateStaticPath()
}) })
@ -102,8 +102,8 @@ function removeHLSFileObjectStorageByFullKey (key: string) {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function removeWebTorrentObjectStorage (videoFile: MVideoFile) { function removeWebVideoObjectStorage (videoFile: MVideoFile) {
return removeObject(generateWebTorrentObjectStorageKey(videoFile.filename), CONFIG.OBJECT_STORAGE.VIDEOS) return removeObject(generateWebVideoObjectStorageKey(videoFile.filename), CONFIG.OBJECT_STORAGE.VIDEOS)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -122,10 +122,10 @@ async function makeHLSFileAvailable (playlist: MStreamingPlaylistVideo, filename
return destination return destination
} }
async function makeWebTorrentFileAvailable (filename: string, destination: string) { async function makeWebVideoFileAvailable (filename: string, destination: string) {
const key = generateWebTorrentObjectStorageKey(filename) const key = generateWebVideoObjectStorageKey(filename)
logger.info('Fetching WebTorrent file %s from object storage to %s.', key, destination, lTags()) logger.info('Fetching Web Video file %s from object storage to %s.', key, destination, lTags())
await makeAvailable({ await makeAvailable({
key, key,
@ -138,13 +138,13 @@ async function makeWebTorrentFileAvailable (filename: string, destination: strin
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function getWebTorrentFileReadStream (options: { function getWebVideoFileReadStream (options: {
filename: string filename: string
rangeHeader: string rangeHeader: string
}) { }) {
const { filename, rangeHeader } = options const { filename, rangeHeader } = options
const key = generateWebTorrentObjectStorageKey(filename) const key = generateWebVideoObjectStorageKey(filename)
return createObjectReadStream({ return createObjectReadStream({
key, key,
@ -174,12 +174,12 @@ function getHLSFileReadStream (options: {
export { export {
listHLSFileKeysOf, listHLSFileKeysOf,
storeWebTorrentFile, storeWebVideoFile,
storeHLSFileFromFilename, storeHLSFileFromFilename,
storeHLSFileFromPath, storeHLSFileFromPath,
storeHLSFileFromContent, storeHLSFileFromContent,
updateWebTorrentFileACL, updateWebVideoFileACL,
updateHLSFilesACL, updateHLSFilesACL,
removeHLSObjectStorage, removeHLSObjectStorage,
@ -187,11 +187,11 @@ export {
removeHLSFileObjectStorageByPath, removeHLSFileObjectStorageByPath,
removeHLSFileObjectStorageByFullKey, removeHLSFileObjectStorageByFullKey,
removeWebTorrentObjectStorage, removeWebVideoObjectStorage,
makeWebTorrentFileAvailable, makeWebVideoFileAvailable,
makeHLSFileAvailable, makeHLSFileAvailable,
getWebTorrentFileReadStream, getWebVideoFileReadStream,
getHLSFileReadStream getHLSFileReadStream
} }

View File

@ -8,7 +8,7 @@ import { isVideoInPrivateDirectory } from './video-privacy'
// ################## Video file name ################## // ################## Video file name ##################
function generateWebTorrentVideoFilename (resolution: number, extname: string) { function generateWebVideoFilename (resolution: number, extname: string) {
return buildUUID() + '-' + resolution + extname return buildUUID() + '-' + resolution + extname
} }
@ -76,7 +76,7 @@ function getFSTorrentFilePath (videoFile: MVideoFile) {
export { export {
generateHLSVideoFilename, generateHLSVideoFilename,
generateWebTorrentVideoFilename, generateWebVideoFilename,
generateTorrentFileName, generateTorrentFileName,
getFSTorrentFilePath, getFSTorrentFilePath,

View File

@ -104,7 +104,7 @@ function buildVideosHelpers () {
const video = await VideoModel.loadFull(id) const video = await VideoModel.loadFull(id)
if (!video) return undefined if (!video) return undefined
const webtorrentVideoFiles = (video.VideoFiles || []).map(f => ({ const webVideoFiles = (video.VideoFiles || []).map(f => ({
path: f.storage === VideoStorage.FILE_SYSTEM path: f.storage === VideoStorage.FILE_SYSTEM
? VideoPathManager.Instance.getFSVideoFileOutputPath(video, f) ? VideoPathManager.Instance.getFSVideoFileOutputPath(video, f)
: null, : null,
@ -138,8 +138,12 @@ function buildVideosHelpers () {
})) }))
return { return {
webtorrent: { webtorrent: { // TODO: remove in v7
videoFiles: webtorrentVideoFiles videoFiles: webVideoFiles
},
webVideo: {
videoFiles: webVideoFiles
}, },
hls: { hls: {

View File

@ -2,7 +2,7 @@ import { move } from 'fs-extra'
import { dirname, join } from 'path' import { dirname, join } from 'path'
import { logger, LoggerTagsFn } from '@server/helpers/logger' import { logger, LoggerTagsFn } from '@server/helpers/logger'
import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding' import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding'
import { onWebTorrentVideoFileTranscoding } from '@server/lib/transcoding/web-transcoding' import { onWebVideoFileTranscoding } from '@server/lib/transcoding/web-transcoding'
import { buildNewFile } from '@server/lib/video-file' import { buildNewFile } from '@server/lib/video-file'
import { VideoModel } from '@server/models/video/video' import { VideoModel } from '@server/models/video/video'
import { MVideoFullLight } from '@server/types/models' import { MVideoFullLight } from '@server/types/models'
@ -22,7 +22,7 @@ export async function onVODWebVideoOrAudioMergeTranscodingJob (options: {
const newVideoFilePath = join(dirname(videoFilePath), videoFile.filename) const newVideoFilePath = join(dirname(videoFilePath), videoFile.filename)
await move(videoFilePath, newVideoFilePath) await move(videoFilePath, newVideoFilePath)
await onWebTorrentVideoFileTranscoding({ await onWebVideoFileTranscoding({
video, video,
videoFile, videoFile,
videoOutputPath: newVideoFilePath videoOutputPath: newVideoFilePath

View File

@ -83,7 +83,7 @@ export class VODAudioMergeTranscodingJobHandler extends AbstractVODTranscodingJo
// We can remove the old audio file // We can remove the old audio file
const oldAudioFile = video.VideoFiles[0] const oldAudioFile = video.VideoFiles[0]
await video.removeWebTorrentFile(oldAudioFile) await video.removeWebVideoFile(oldAudioFile)
await oldAudioFile.destroy() await oldAudioFile.destroy()
video.VideoFiles = [] video.VideoFiles = []

View File

@ -5,7 +5,7 @@ import { renameVideoFileInPlaylist } from '@server/lib/hls'
import { getHlsResolutionPlaylistFilename } from '@server/lib/paths' import { getHlsResolutionPlaylistFilename } from '@server/lib/paths'
import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding' import { onTranscodingEnded } from '@server/lib/transcoding/ended-transcoding'
import { onHLSVideoFileTranscoding } from '@server/lib/transcoding/hls-transcoding' import { onHLSVideoFileTranscoding } from '@server/lib/transcoding/hls-transcoding'
import { buildNewFile, removeAllWebTorrentFiles } from '@server/lib/video-file' import { buildNewFile, removeAllWebVideoFiles } from '@server/lib/video-file'
import { VideoJobInfoModel } from '@server/models/video/video-job-info' import { VideoJobInfoModel } from '@server/models/video/video-job-info'
import { MVideo } from '@server/types/models' import { MVideo } from '@server/types/models'
import { MRunnerJob } from '@server/types/models/runners' import { MRunnerJob } from '@server/types/models/runners'
@ -106,7 +106,7 @@ export class VODHLSTranscodingJobHandler extends AbstractVODTranscodingJobHandle
if (privatePayload.deleteWebVideoFiles === true) { if (privatePayload.deleteWebVideoFiles === true) {
logger.info('Removing web video files of %s now we have a HLS version of it.', video.uuid, this.lTags(video.uuid)) logger.info('Removing web video files of %s now we have a HLS version of it.', video.uuid, this.lTags(video.uuid))
await removeAllWebTorrentFiles(video) await removeAllWebVideoFiles(video)
} }
logger.info('Runner VOD HLS job %s for %s ended.', runnerJob.uuid, video.uuid, this.lTags(runnerJob.uuid, video.uuid)) logger.info('Runner VOD HLS job %s for %s ended.', runnerJob.uuid, video.uuid, this.lTags(runnerJob.uuid, video.uuid))

View File

@ -23,7 +23,7 @@ import { getLocalVideoCacheFileActivityPubUrl, getLocalVideoCacheStreamingPlayli
import { getOrCreateAPVideo } from '../activitypub/videos' import { getOrCreateAPVideo } from '../activitypub/videos'
import { downloadPlaylistSegments } from '../hls' import { downloadPlaylistSegments } from '../hls'
import { removeVideoRedundancy } from '../redundancy' import { removeVideoRedundancy } from '../redundancy'
import { generateHLSRedundancyUrl, generateWebTorrentRedundancyUrl } from '../video-urls' import { generateHLSRedundancyUrl, generateWebVideoRedundancyUrl } from '../video-urls'
import { AbstractScheduler } from './abstract-scheduler' import { AbstractScheduler } from './abstract-scheduler'
const lTags = loggerTagsFactory('redundancy') const lTags = loggerTagsFactory('redundancy')
@ -244,7 +244,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
const createdModel: MVideoRedundancyFileVideo = await VideoRedundancyModel.create({ const createdModel: MVideoRedundancyFileVideo = await VideoRedundancyModel.create({
expiresOn, expiresOn,
url: getLocalVideoCacheFileActivityPubUrl(file), url: getLocalVideoCacheFileActivityPubUrl(file),
fileUrl: generateWebTorrentRedundancyUrl(file), fileUrl: generateWebVideoRedundancyUrl(file),
strategy, strategy,
videoFileId: file.id, videoFileId: file.id,
actorId: serverActor.id actorId: serverActor.id

View File

@ -15,7 +15,7 @@ export function createOptimizeOrMergeAudioJobs (options: {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
export function createTranscodingJobs (options: { export function createTranscodingJobs (options: {
transcodingType: 'hls' | 'webtorrent' transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
video: MVideoFullLight video: MVideoFullLight
resolutions: number[] resolutions: number[]
isNewVideo: boolean isNewVideo: boolean

View File

@ -12,7 +12,7 @@ export abstract class AbstractJobBuilder {
}): Promise<any> }): Promise<any>
abstract createTranscodingJobs (options: { abstract createTranscodingJobs (options: {
transcodingType: 'hls' | 'webtorrent' transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
video: MVideoFullLight video: MVideoFullLight
resolutions: number[] resolutions: number[]
isNewVideo: boolean isNewVideo: boolean

View File

@ -12,7 +12,7 @@ import { ffprobePromise, getVideoStreamDimensionsInfo, getVideoStreamFPS, hasAud
import { import {
HLSTranscodingPayload, HLSTranscodingPayload,
MergeAudioTranscodingPayload, MergeAudioTranscodingPayload,
NewWebTorrentResolutionTranscodingPayload, NewWebVideoResolutionTranscodingPayload,
OptimizeTranscodingPayload, OptimizeTranscodingPayload,
VideoTranscodingPayload VideoTranscodingPayload
} from '@shared/models' } from '@shared/models'
@ -33,7 +33,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
const { video, videoFile, isNewVideo, user, videoFileAlreadyLocked } = options const { video, videoFile, isNewVideo, user, videoFileAlreadyLocked } = options
let mergeOrOptimizePayload: MergeAudioTranscodingPayload | OptimizeTranscodingPayload let mergeOrOptimizePayload: MergeAudioTranscodingPayload | OptimizeTranscodingPayload
let nextTranscodingSequentialJobPayloads: (NewWebTorrentResolutionTranscodingPayload | HLSTranscodingPayload)[][] = [] let nextTranscodingSequentialJobPayloads: (NewWebVideoResolutionTranscodingPayload | HLSTranscodingPayload)[][] = []
const mutexReleaser = videoFileAlreadyLocked const mutexReleaser = videoFileAlreadyLocked
? () => {} ? () => {}
@ -60,7 +60,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
if (CONFIG.TRANSCODING.HLS.ENABLED === true) { if (CONFIG.TRANSCODING.HLS.ENABLED === true) {
nextTranscodingSequentialJobPayloads.push([ nextTranscodingSequentialJobPayloads.push([
this.buildHLSJobPayload({ this.buildHLSJobPayload({
deleteWebTorrentFiles: CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false, deleteWebVideoFiles: CONFIG.TRANSCODING.WEBTORRENT.ENABLED === false,
// We had some issues with a web video quick transcoded while producing a HLS version of it // We had some issues with a web video quick transcoded while producing a HLS version of it
copyCodecs: !quickTranscode, copyCodecs: !quickTranscode,
@ -116,7 +116,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async createTranscodingJobs (options: { async createTranscodingJobs (options: {
transcodingType: 'hls' | 'webtorrent' transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
video: MVideoFullLight video: MVideoFullLight
resolutions: number[] resolutions: number[]
isNewVideo: boolean isNewVideo: boolean
@ -138,8 +138,8 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
return this.buildHLSJobPayload({ videoUUID: video.uuid, resolution, fps, isNewVideo }) return this.buildHLSJobPayload({ videoUUID: video.uuid, resolution, fps, isNewVideo })
} }
if (transcodingType === 'webtorrent') { if (transcodingType === 'webtorrent' || transcodingType === 'web-video') {
return this.buildWebTorrentJobPayload({ videoUUID: video.uuid, resolution, fps, isNewVideo }) return this.buildWebVideoJobPayload({ videoUUID: video.uuid, resolution, fps, isNewVideo })
} }
throw new Error('Unknown transcoding type') throw new Error('Unknown transcoding type')
@ -149,7 +149,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
const parent = transcodingType === 'hls' const parent = transcodingType === 'hls'
? this.buildHLSJobPayload({ videoUUID: video.uuid, resolution: maxResolution, fps, isNewVideo }) ? this.buildHLSJobPayload({ videoUUID: video.uuid, resolution: maxResolution, fps, isNewVideo })
: this.buildWebTorrentJobPayload({ videoUUID: video.uuid, resolution: maxResolution, fps, isNewVideo }) : this.buildWebVideoJobPayload({ videoUUID: video.uuid, resolution: maxResolution, fps, isNewVideo })
// Process the last resolution after the other ones to prevent concurrency issue // Process the last resolution after the other ones to prevent concurrency issue
// Because low resolutions use the biggest one as ffmpeg input // Because low resolutions use the biggest one as ffmpeg input
@ -160,8 +160,8 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
private async createTranscodingJobsWithChildren (options: { private async createTranscodingJobsWithChildren (options: {
videoUUID: string videoUUID: string
parent: (HLSTranscodingPayload | NewWebTorrentResolutionTranscodingPayload) parent: (HLSTranscodingPayload | NewWebVideoResolutionTranscodingPayload)
children: (HLSTranscodingPayload | NewWebTorrentResolutionTranscodingPayload)[] children: (HLSTranscodingPayload | NewWebVideoResolutionTranscodingPayload)[]
user: MUserId | null user: MUserId | null
}) { }) {
const { videoUUID, parent, children, user } = options const { videoUUID, parent, children, user } = options
@ -203,14 +203,14 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
options options
) )
const sequentialPayloads: (NewWebTorrentResolutionTranscodingPayload | HLSTranscodingPayload)[][] = [] const sequentialPayloads: (NewWebVideoResolutionTranscodingPayload | HLSTranscodingPayload)[][] = []
for (const resolution of resolutionsEnabled) { for (const resolution of resolutionsEnabled) {
const fps = computeOutputFPS({ inputFPS: inputVideoFPS, resolution }) const fps = computeOutputFPS({ inputFPS: inputVideoFPS, resolution })
if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED) { if (CONFIG.TRANSCODING.WEBTORRENT.ENABLED) {
const payloads: (NewWebTorrentResolutionTranscodingPayload | HLSTranscodingPayload)[] = [ const payloads: (NewWebVideoResolutionTranscodingPayload | HLSTranscodingPayload)[] = [
this.buildWebTorrentJobPayload({ this.buildWebVideoJobPayload({
videoUUID: video.uuid, videoUUID: video.uuid,
resolution, resolution,
fps, fps,
@ -253,10 +253,10 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
resolution: number resolution: number
fps: number fps: number
isNewVideo: boolean isNewVideo: boolean
deleteWebTorrentFiles?: boolean // default false deleteWebVideoFiles?: boolean // default false
copyCodecs?: boolean // default false copyCodecs?: boolean // default false
}): HLSTranscodingPayload { }): HLSTranscodingPayload {
const { videoUUID, resolution, fps, isNewVideo, deleteWebTorrentFiles = false, copyCodecs = false } = options const { videoUUID, resolution, fps, isNewVideo, deleteWebVideoFiles = false, copyCodecs = false } = options
return { return {
type: 'new-resolution-to-hls', type: 'new-resolution-to-hls',
@ -265,20 +265,20 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
fps, fps,
copyCodecs, copyCodecs,
isNewVideo, isNewVideo,
deleteWebTorrentFiles deleteWebVideoFiles
} }
} }
private buildWebTorrentJobPayload (options: { private buildWebVideoJobPayload (options: {
videoUUID: string videoUUID: string
resolution: number resolution: number
fps: number fps: number
isNewVideo: boolean isNewVideo: boolean
}): NewWebTorrentResolutionTranscodingPayload { }): NewWebVideoResolutionTranscodingPayload {
const { videoUUID, resolution, fps, isNewVideo } = options const { videoUUID, resolution, fps, isNewVideo } = options
return { return {
type: 'new-resolution-to-webtorrent', type: 'new-resolution-to-web-video',
videoUUID, videoUUID,
isNewVideo, isNewVideo,
resolution, resolution,
@ -294,7 +294,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
const { videoUUID, isNewVideo, hasChildren } = options const { videoUUID, isNewVideo, hasChildren } = options
return { return {
type: 'merge-audio-to-webtorrent', type: 'merge-audio-to-web-video',
resolution: DEFAULT_AUDIO_RESOLUTION, resolution: DEFAULT_AUDIO_RESOLUTION,
fps: VIDEO_TRANSCODING_FPS.AUDIO_MERGE, fps: VIDEO_TRANSCODING_FPS.AUDIO_MERGE,
videoUUID, videoUUID,
@ -312,7 +312,7 @@ export class TranscodingJobQueueBuilder extends AbstractJobBuilder {
const { videoUUID, quickTranscode, isNewVideo, hasChildren } = options const { videoUUID, quickTranscode, isNewVideo, hasChildren } = options
return { return {
type: 'optimize-to-webtorrent', type: 'optimize-to-web-video',
videoUUID, videoUUID,
isNewVideo, isNewVideo,
hasChildren, hasChildren,

View File

@ -89,7 +89,7 @@ export class TranscodingRunnerJobBuilder extends AbstractJobBuilder {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async createTranscodingJobs (options: { async createTranscodingJobs (options: {
transcodingType: 'hls' | 'webtorrent' transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
video: MVideoFullLight video: MVideoFullLight
resolutions: number[] resolutions: number[]
isNewVideo: boolean isNewVideo: boolean
@ -130,7 +130,7 @@ export class TranscodingRunnerJobBuilder extends AbstractJobBuilder {
continue continue
} }
if (transcodingType === 'webtorrent') { if (transcodingType === 'webtorrent' || transcodingType === 'web-video') {
await new VODWebVideoTranscodingJobHandler().create({ await new VODWebVideoTranscodingJobHandler().create({
video, video,
resolution, resolution,

View File

@ -10,7 +10,7 @@ import { VideoResolution, VideoStorage } from '@shared/models'
import { CONFIG } from '../../initializers/config' import { CONFIG } from '../../initializers/config'
import { VideoFileModel } from '../../models/video/video-file' import { VideoFileModel } from '../../models/video/video-file'
import { JobQueue } from '../job-queue' import { JobQueue } from '../job-queue'
import { generateWebTorrentVideoFilename } from '../paths' import { generateWebVideoFilename } from '../paths'
import { buildFileMetadata } from '../video-file' import { buildFileMetadata } from '../video-file'
import { VideoPathManager } from '../video-path-manager' import { VideoPathManager } from '../video-path-manager'
import { buildFFmpegVOD } from './shared' import { buildFFmpegVOD } from './shared'
@ -63,10 +63,10 @@ export async function optimizeOriginalVideofile (options: {
// Important to do this before getVideoFilename() to take in account the new filename // Important to do this before getVideoFilename() to take in account the new filename
inputVideoFile.resolution = resolution inputVideoFile.resolution = resolution
inputVideoFile.extname = newExtname inputVideoFile.extname = newExtname
inputVideoFile.filename = generateWebTorrentVideoFilename(resolution, newExtname) inputVideoFile.filename = generateWebVideoFilename(resolution, newExtname)
inputVideoFile.storage = VideoStorage.FILE_SYSTEM inputVideoFile.storage = VideoStorage.FILE_SYSTEM
const { videoFile } = await onWebTorrentVideoFileTranscoding({ const { videoFile } = await onWebVideoFileTranscoding({
video, video,
videoFile: inputVideoFile, videoFile: inputVideoFile,
videoOutputPath videoOutputPath
@ -83,8 +83,8 @@ export async function optimizeOriginalVideofile (options: {
} }
} }
// Transcode the original video file to a lower resolution compatible with WebTorrent // Transcode the original video file to a lower resolution compatible with web browsers
export async function transcodeNewWebTorrentResolution (options: { export async function transcodeNewWebVideoResolution (options: {
video: MVideoFullLight video: MVideoFullLight
resolution: VideoResolution resolution: VideoResolution
fps: number fps: number
@ -105,7 +105,7 @@ export async function transcodeNewWebTorrentResolution (options: {
const newVideoFile = new VideoFileModel({ const newVideoFile = new VideoFileModel({
resolution, resolution,
extname: newExtname, extname: newExtname,
filename: generateWebTorrentVideoFilename(resolution, newExtname), filename: generateWebVideoFilename(resolution, newExtname),
size: 0, size: 0,
videoId: video.id videoId: video.id
}) })
@ -126,7 +126,7 @@ export async function transcodeNewWebTorrentResolution (options: {
await buildFFmpegVOD(job).transcode(transcodeOptions) await buildFFmpegVOD(job).transcode(transcodeOptions)
return onWebTorrentVideoFileTranscoding({ video, videoFile: newVideoFile, videoOutputPath }) return onWebVideoFileTranscoding({ video, videoFile: newVideoFile, videoOutputPath })
}) })
return result return result
@ -189,14 +189,14 @@ export async function mergeAudioVideofile (options: {
// Important to do this before getVideoFilename() to take in account the new file extension // Important to do this before getVideoFilename() to take in account the new file extension
inputVideoFile.extname = newExtname inputVideoFile.extname = newExtname
inputVideoFile.resolution = resolution inputVideoFile.resolution = resolution
inputVideoFile.filename = generateWebTorrentVideoFilename(inputVideoFile.resolution, newExtname) inputVideoFile.filename = generateWebVideoFilename(inputVideoFile.resolution, newExtname)
// ffmpeg generated a new video file, so update the video duration // ffmpeg generated a new video file, so update the video duration
// See https://trac.ffmpeg.org/ticket/5456 // See https://trac.ffmpeg.org/ticket/5456
video.duration = await getVideoStreamDuration(videoOutputPath) video.duration = await getVideoStreamDuration(videoOutputPath)
await video.save() await video.save()
return onWebTorrentVideoFileTranscoding({ return onWebVideoFileTranscoding({
video, video,
videoFile: inputVideoFile, videoFile: inputVideoFile,
videoOutputPath, videoOutputPath,
@ -210,7 +210,7 @@ export async function mergeAudioVideofile (options: {
} }
} }
export async function onWebTorrentVideoFileTranscoding (options: { export async function onWebVideoFileTranscoding (options: {
video: MVideoFullLight video: MVideoFullLight
videoFile: MVideoFile videoFile: MVideoFile
videoOutputPath: string videoOutputPath: string
@ -239,8 +239,8 @@ export async function onWebTorrentVideoFileTranscoding (options: {
await createTorrentAndSetInfoHash(video, videoFile) await createTorrentAndSetInfoHash(video, videoFile)
const oldFile = await VideoFileModel.loadWebTorrentFile({ videoId: video.id, fps: videoFile.fps, resolution: videoFile.resolution }) const oldFile = await VideoFileModel.loadWebVideoFile({ videoId: video.id, fps: videoFile.fps, resolution: videoFile.resolution })
if (oldFile) await video.removeWebTorrentFile(oldFile) if (oldFile) await video.removeWebVideoFile(oldFile)
await VideoFileModel.customUpsert(videoFile, 'video', undefined) await VideoFileModel.customUpsert(videoFile, 'video', undefined)
video.VideoFiles = await video.$get('VideoFiles') video.VideoFiles = await video.$get('VideoFiles')

View File

@ -7,7 +7,7 @@ import { getFileSize } from '@shared/extra-utils'
import { ffprobePromise, getVideoStreamDimensionsInfo, getVideoStreamFPS, isAudioFile } from '@shared/ffmpeg' import { ffprobePromise, getVideoStreamDimensionsInfo, getVideoStreamFPS, isAudioFile } from '@shared/ffmpeg'
import { VideoFileMetadata, VideoResolution } from '@shared/models' import { VideoFileMetadata, VideoResolution } from '@shared/models'
import { lTags } from './object-storage/shared' import { lTags } from './object-storage/shared'
import { generateHLSVideoFilename, generateWebTorrentVideoFilename } from './paths' import { generateHLSVideoFilename, generateWebVideoFilename } from './paths'
import { VideoPathManager } from './video-path-manager' import { VideoPathManager } from './video-path-manager'
async function buildNewFile (options: { async function buildNewFile (options: {
@ -33,7 +33,7 @@ async function buildNewFile (options: {
} }
videoFile.filename = mode === 'web-video' videoFile.filename = mode === 'web-video'
? generateWebTorrentVideoFilename(videoFile.resolution, videoFile.extname) ? generateWebVideoFilename(videoFile.resolution, videoFile.extname)
: generateHLSVideoFilename(videoFile.resolution) : generateHLSVideoFilename(videoFile.resolution)
return videoFile return videoFile
@ -85,12 +85,12 @@ async function removeHLSFile (video: MVideoWithAllFiles, fileToDeleteId: number)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function removeAllWebTorrentFiles (video: MVideoWithAllFiles) { async function removeAllWebVideoFiles (video: MVideoWithAllFiles) {
const videoFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid) const videoFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid)
try { try {
for (const file of video.VideoFiles) { for (const file of video.VideoFiles) {
await video.removeWebTorrentFile(file) await video.removeWebVideoFile(file)
await file.destroy() await file.destroy()
} }
@ -102,17 +102,17 @@ async function removeAllWebTorrentFiles (video: MVideoWithAllFiles) {
return video return video
} }
async function removeWebTorrentFile (video: MVideoWithAllFiles, fileToDeleteId: number) { async function removeWebVideoFile (video: MVideoWithAllFiles, fileToDeleteId: number) {
const files = video.VideoFiles const files = video.VideoFiles
if (files.length === 1) { if (files.length === 1) {
return removeAllWebTorrentFiles(video) return removeAllWebVideoFiles(video)
} }
const videoFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid) const videoFileMutexReleaser = await VideoPathManager.Instance.lockFiles(video.uuid)
try { try {
const toDelete = files.find(f => f.id === fileToDeleteId) const toDelete = files.find(f => f.id === fileToDeleteId)
await video.removeWebTorrentFile(toDelete) await video.removeWebVideoFile(toDelete)
await toDelete.destroy() await toDelete.destroy()
video.VideoFiles = files.filter(f => f.id !== toDelete.id) video.VideoFiles = files.filter(f => f.id !== toDelete.id)
@ -138,8 +138,8 @@ export {
removeHLSPlaylist, removeHLSPlaylist,
removeHLSFile, removeHLSFile,
removeAllWebTorrentFiles, removeAllWebVideoFiles,
removeWebTorrentFile, removeWebVideoFile,
buildFileMetadata buildFileMetadata
} }

View File

@ -8,7 +8,7 @@ import { DIRECTORIES } from '@server/initializers/constants'
import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoFileStreamingPlaylistVideo, MVideoFileVideo } from '@server/types/models' import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoFileStreamingPlaylistVideo, MVideoFileVideo } from '@server/types/models'
import { buildUUID } from '@shared/extra-utils' import { buildUUID } from '@shared/extra-utils'
import { VideoStorage } from '@shared/models' import { VideoStorage } from '@shared/models'
import { makeHLSFileAvailable, makeWebTorrentFileAvailable } from './object-storage' import { makeHLSFileAvailable, makeWebVideoFileAvailable } from './object-storage'
import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from './paths' import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from './paths'
import { isVideoInPrivateDirectory } from './video-privacy' import { isVideoInPrivateDirectory } from './video-privacy'
@ -78,7 +78,7 @@ class VideoPathManager {
} }
return this.makeAvailableFactory( return this.makeAvailableFactory(
() => makeWebTorrentFileAvailable(videoFile.filename, destination), () => makeWebVideoFileAvailable(videoFile.filename, destination),
true, true,
cb cb
) )

View File

@ -4,7 +4,7 @@ import { logger } from '@server/helpers/logger'
import { DIRECTORIES } from '@server/initializers/constants' import { DIRECTORIES } from '@server/initializers/constants'
import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' import { MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
import { VideoPrivacy, VideoStorage } from '@shared/models' import { VideoPrivacy, VideoStorage } from '@shared/models'
import { updateHLSFilesACL, updateWebTorrentFileACL } from './object-storage' import { updateHLSFilesACL, updateWebVideoFileACL } from './object-storage'
const validPrivacySet = new Set([ const validPrivacySet = new Set([
VideoPrivacy.PRIVATE, VideoPrivacy.PRIVATE,
@ -67,9 +67,9 @@ async function moveFiles (options: {
for (const file of video.VideoFiles) { for (const file of video.VideoFiles) {
if (file.storage === VideoStorage.FILE_SYSTEM) { if (file.storage === VideoStorage.FILE_SYSTEM) {
await moveWebTorrentFileOnFS(type, video, file) await moveWebVideoFileOnFS(type, video, file)
} else { } else {
await updateWebTorrentFileACL(video, file) await updateWebVideoFileACL(video, file)
} }
} }
@ -84,22 +84,22 @@ async function moveFiles (options: {
} }
} }
async function moveWebTorrentFileOnFS (type: MoveType, video: MVideo, file: MVideoFile) { async function moveWebVideoFileOnFS (type: MoveType, video: MVideo, file: MVideoFile) {
const directories = getWebTorrentDirectories(type) const directories = getWebVideoDirectories(type)
const source = join(directories.old, file.filename) const source = join(directories.old, file.filename)
const destination = join(directories.new, file.filename) const destination = join(directories.new, file.filename)
try { try {
logger.info('Moving WebTorrent files of %s after privacy change (%s -> %s).', video.uuid, source, destination) logger.info('Moving web video files of %s after privacy change (%s -> %s).', video.uuid, source, destination)
await move(source, destination) await move(source, destination)
} catch (err) { } catch (err) {
logger.error('Cannot move webtorrent file %s to %s after privacy change', source, destination, { err }) logger.error('Cannot move web video file %s to %s after privacy change', source, destination, { err })
} }
} }
function getWebTorrentDirectories (moveType: MoveType) { function getWebVideoDirectories (moveType: MoveType) {
if (moveType === 'private-to-public') { if (moveType === 'private-to-public') {
return { old: DIRECTORIES.VIDEOS.PRIVATE, new: DIRECTORIES.VIDEOS.PUBLIC } return { old: DIRECTORIES.VIDEOS.PRIVATE, new: DIRECTORIES.VIDEOS.PUBLIC }
} }

View File

@ -12,7 +12,7 @@ import { JobQueue } from './job-queue'
import { VideoStudioTranscodingJobHandler } from './runners' import { VideoStudioTranscodingJobHandler } from './runners'
import { createOptimizeOrMergeAudioJobs } from './transcoding/create-transcoding-job' import { createOptimizeOrMergeAudioJobs } from './transcoding/create-transcoding-job'
import { getTranscodingJobPriority } from './transcoding/transcoding-priority' import { getTranscodingJobPriority } from './transcoding/transcoding-priority'
import { buildNewFile, removeHLSPlaylist, removeWebTorrentFile } from './video-file' import { buildNewFile, removeHLSPlaylist, removeWebVideoFile } from './video-file'
import { VideoPathManager } from './video-path-manager' import { VideoPathManager } from './video-path-manager'
const lTags = loggerTagsFactory('video-studio') const lTags = loggerTagsFactory('video-studio')
@ -119,12 +119,12 @@ export async function onVideoStudioEnded (options: {
// Private // Private
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function removeAllFiles (video: MVideoWithAllFiles, webTorrentFileException: MVideoFile) { async function removeAllFiles (video: MVideoWithAllFiles, webVideoFileException: MVideoFile) {
await removeHLSPlaylist(video) await removeHLSPlaylist(video)
for (const file of video.VideoFiles) { for (const file of video.VideoFiles) {
if (file.id === webTorrentFileException.id) continue if (file.id === webVideoFileException.id) continue
await removeWebTorrentFile(video, file.id) await removeWebVideoFile(video, file.id)
} }
} }

View File

@ -9,7 +9,7 @@ function generateHLSRedundancyUrl (video: MVideo, playlist: MStreamingPlaylist)
return WEBSERVER.URL + STATIC_PATHS.REDUNDANCY + playlist.getStringType() + '/' + video.uuid return WEBSERVER.URL + STATIC_PATHS.REDUNDANCY + playlist.getStringType() + '/' + video.uuid
} }
function generateWebTorrentRedundancyUrl (file: MVideoFile) { function generateWebVideoRedundancyUrl (file: MVideoFile) {
return WEBSERVER.URL + STATIC_PATHS.REDUNDANCY + file.filename return WEBSERVER.URL + STATIC_PATHS.REDUNDANCY + file.filename
} }
@ -26,6 +26,6 @@ function getLocalVideoFileMetadataUrl (video: MVideoUUID, videoFile: MVideoFile)
export { export {
getLocalVideoFileMetadataUrl, getLocalVideoFileMetadataUrl,
generateWebTorrentRedundancyUrl, generateWebVideoRedundancyUrl,
generateHLSRedundancyUrl generateHLSRedundancyUrl
} }

View File

@ -22,7 +22,7 @@ const staticFileTokenBypass = new LRUCache<string, LRUValue>({
ttl: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL ttl: LRU_CACHE.STATIC_VIDEO_FILES_RIGHTS_CHECK.TTL
}) })
const ensureCanAccessVideoPrivateWebTorrentFiles = [ const ensureCanAccessVideoPrivateWebVideoFiles = [
query('videoFileToken').optional().custom(exists), query('videoFileToken').optional().custom(exists),
isValidVideoPasswordHeader(), isValidVideoPasswordHeader(),
@ -48,7 +48,7 @@ const ensureCanAccessVideoPrivateWebTorrentFiles = [
return res.sendStatus(HttpStatusCode.FORBIDDEN_403) return res.sendStatus(HttpStatusCode.FORBIDDEN_403)
} }
const result = await isWebTorrentAllowed(req, res) const result = await isWebVideoAllowed(req, res)
staticFileTokenBypass.set(cacheKey, result) staticFileTokenBypass.set(cacheKey, result)
@ -122,13 +122,13 @@ const ensureCanAccessPrivateVideoHLSFiles = [
] ]
export { export {
ensureCanAccessVideoPrivateWebTorrentFiles, ensureCanAccessVideoPrivateWebVideoFiles,
ensureCanAccessPrivateVideoHLSFiles ensureCanAccessPrivateVideoHLSFiles
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function isWebTorrentAllowed (req: express.Request, res: express.Response) { async function isWebVideoAllowed (req: express.Request, res: express.Response) {
const filename = basename(req.path) const filename = basename(req.path)
const file = await VideoFileModel.loadWithVideoByFilename(filename) const file = await VideoFileModel.loadWithVideoByFilename(filename)

View File

@ -5,7 +5,7 @@ import { MVideo } from '@server/types/models'
import { HttpStatusCode } from '@shared/models' import { HttpStatusCode } from '@shared/models'
import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared' import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared'
const videoFilesDeleteWebTorrentValidator = [ const videoFilesDeleteWebVideoValidator = [
isValidVideoIdParam('id'), isValidVideoIdParam('id'),
async (req: express.Request, res: express.Response, next: express.NextFunction) => { async (req: express.Request, res: express.Response, next: express.NextFunction) => {
@ -16,17 +16,17 @@ const videoFilesDeleteWebTorrentValidator = [
if (!checkLocalVideo(video, res)) return if (!checkLocalVideo(video, res)) return
if (!video.hasWebTorrentFiles()) { if (!video.hasWebVideoFiles()) {
return res.fail({ return res.fail({
status: HttpStatusCode.BAD_REQUEST_400, status: HttpStatusCode.BAD_REQUEST_400,
message: 'This video does not have WebTorrent files' message: 'This video does not have Web Video files'
}) })
} }
if (!video.getHLSPlaylist()) { if (!video.getHLSPlaylist()) {
return res.fail({ return res.fail({
status: HttpStatusCode.BAD_REQUEST_400, status: HttpStatusCode.BAD_REQUEST_400,
message: 'Cannot delete WebTorrent files since this video does not have HLS playlist' message: 'Cannot delete Web Video files since this video does not have HLS playlist'
}) })
} }
@ -34,7 +34,7 @@ const videoFilesDeleteWebTorrentValidator = [
} }
] ]
const videoFilesDeleteWebTorrentFileValidator = [ const videoFilesDeleteWebVideoFileValidator = [
isValidVideoIdParam('id'), isValidVideoIdParam('id'),
param('videoFileId') param('videoFileId')
@ -52,14 +52,14 @@ const videoFilesDeleteWebTorrentFileValidator = [
if (!files.find(f => f.id === +req.params.videoFileId)) { if (!files.find(f => f.id === +req.params.videoFileId)) {
return res.fail({ return res.fail({
status: HttpStatusCode.NOT_FOUND_404, status: HttpStatusCode.NOT_FOUND_404,
message: 'This video does not have this WebTorrent file id' message: 'This video does not have this Web Video file id'
}) })
} }
if (files.length === 1 && !video.getHLSPlaylist()) { if (files.length === 1 && !video.getHLSPlaylist()) {
return res.fail({ return res.fail({
status: HttpStatusCode.BAD_REQUEST_400, status: HttpStatusCode.BAD_REQUEST_400,
message: 'Cannot delete WebTorrent files since this video does not have HLS playlist' message: 'Cannot delete Web Video files since this video does not have HLS playlist'
}) })
} }
@ -87,10 +87,10 @@ const videoFilesDeleteHLSValidator = [
}) })
} }
if (!video.hasWebTorrentFiles()) { if (!video.hasWebVideoFiles()) {
return res.fail({ return res.fail({
status: HttpStatusCode.BAD_REQUEST_400, status: HttpStatusCode.BAD_REQUEST_400,
message: 'Cannot delete HLS playlist since this video does not have WebTorrent files' message: 'Cannot delete HLS playlist since this video does not have Web Video files'
}) })
} }
@ -128,10 +128,10 @@ const videoFilesDeleteHLSFileValidator = [
} }
// Last file to delete // Last file to delete
if (hlsFiles.length === 1 && !video.hasWebTorrentFiles()) { if (hlsFiles.length === 1 && !video.hasWebVideoFiles()) {
return res.fail({ return res.fail({
status: HttpStatusCode.BAD_REQUEST_400, status: HttpStatusCode.BAD_REQUEST_400,
message: 'Cannot delete last HLS playlist file since this video does not have WebTorrent files' message: 'Cannot delete last HLS playlist file since this video does not have Web Video files'
}) })
} }
@ -140,8 +140,8 @@ const videoFilesDeleteHLSFileValidator = [
] ]
export { export {
videoFilesDeleteWebTorrentValidator, videoFilesDeleteWebVideoValidator,
videoFilesDeleteWebTorrentFileValidator, videoFilesDeleteWebVideoFileValidator,
videoFilesDeleteHLSValidator, videoFilesDeleteHLSValidator,
videoFilesDeleteHLSFileValidator videoFilesDeleteHLSFileValidator

View File

@ -506,10 +506,14 @@ const commonVideosFiltersValidator = [
.optional() .optional()
.customSanitizer(toBooleanOrNull) .customSanitizer(toBooleanOrNull)
.custom(isBooleanValid).withMessage('Should have a valid hasHLSFiles boolean'), .custom(isBooleanValid).withMessage('Should have a valid hasHLSFiles boolean'),
query('hasWebtorrentFiles') query('hasWebtorrentFiles') // TODO: remove in v7
.optional() .optional()
.customSanitizer(toBooleanOrNull) .customSanitizer(toBooleanOrNull)
.custom(isBooleanValid).withMessage('Should have a valid hasWebtorrentFiles boolean'), .custom(isBooleanValid).withMessage('Should have a valid hasWebtorrentFiles boolean'),
query('hasWebVideoFiles')
.optional()
.customSanitizer(toBooleanOrNull)
.custom(isBooleanValid).withMessage('Should have a valid hasWebVideoFiles boolean'),
query('skipCount') query('skipCount')
.optional() .optional()
.customSanitizer(toBooleanOrNull) .customSanitizer(toBooleanOrNull)

View File

@ -162,7 +162,7 @@ export class VideoRedundancyModel extends Model<Partial<AttributesOnly<VideoRedu
const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}` const logIdentifier = `${videoFile.Video.uuid}-${videoFile.resolution}`
logger.info('Removing duplicated video file %s.', logIdentifier) logger.info('Removing duplicated video file %s.', logIdentifier)
videoFile.Video.removeWebTorrentFile(videoFile, true) videoFile.Video.removeWebVideoFile(videoFile, true)
.catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err })) .catch(err => logger.error('Cannot delete %s files.', logIdentifier, { err }))
} }

View File

@ -786,7 +786,7 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' + 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' +
`WHERE "account"."userId" = ${options.whereUserId} ${andWhere}` `WHERE "account"."userId" = ${options.whereUserId} ${andWhere}`
const webtorrentFiles = 'SELECT "videoFile"."size" AS "size", "video"."id" AS "videoId" FROM "videoFile" ' + const webVideoFiles = 'SELECT "videoFile"."size" AS "size", "video"."id" AS "videoId" FROM "videoFile" ' +
'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" AND "video"."isLive" IS FALSE ' + 'INNER JOIN "video" ON "videoFile"."videoId" = "video"."id" AND "video"."isLive" IS FALSE ' +
videoChannelJoin videoChannelJoin
@ -797,7 +797,7 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
return 'SELECT COALESCE(SUM("size"), 0) AS "total" ' + return 'SELECT COALESCE(SUM("size"), 0) AS "total" ' +
'FROM (' + 'FROM (' +
`SELECT MAX("t1"."size") AS "size" FROM (${webtorrentFiles} UNION ${hlsFiles}) t1 ` + `SELECT MAX("t1"."size") AS "size" FROM (${webVideoFiles} UNION ${hlsFiles}) t1 ` +
'GROUP BY "t1"."videoId"' + 'GROUP BY "t1"."videoId"' +
') t2' ') t2'
} }
@ -890,8 +890,6 @@ export class UserModel extends Model<Partial<AttributesOnly<UserModel>>> {
nsfwPolicy: this.nsfwPolicy, nsfwPolicy: this.nsfwPolicy,
// FIXME: deprecated in 4.1
webTorrentEnabled: this.p2pEnabled,
p2pEnabled: this.p2pEnabled, p2pEnabled: this.p2pEnabled,
videosHistoryEnabled: this.videosHistoryEnabled, videosHistoryEnabled: this.videosHistoryEnabled,

View File

@ -111,7 +111,7 @@ export class AbstractVideoQueryBuilder extends AbstractRunQuery {
} }
} }
protected includeWebtorrentFiles () { protected includeWebVideoFiles () {
this.addJoin('LEFT JOIN "videoFile" AS "VideoFiles" ON "VideoFiles"."videoId" = "video"."id"') this.addJoin('LEFT JOIN "videoFile" AS "VideoFiles" ON "VideoFiles"."videoId" = "video"."id"')
this.attributes = { this.attributes = {
@ -263,7 +263,7 @@ export class AbstractVideoQueryBuilder extends AbstractRunQuery {
} }
} }
protected includeWebTorrentRedundancies () { protected includeWebVideoRedundancies () {
this.addJoin( this.addJoin(
'LEFT OUTER JOIN "videoRedundancy" AS "VideoFiles->RedundancyVideos" ON ' + 'LEFT OUTER JOIN "videoRedundancy" AS "VideoFiles->RedundancyVideos" ON ' +
'"VideoFiles"."id" = "VideoFiles->RedundancyVideos"."videoFileId"' '"VideoFiles"."id" = "VideoFiles->RedundancyVideos"."videoFileId"'

View File

@ -14,7 +14,7 @@ export type FileQueryOptions = {
/** /**
* *
* Fetch files (webtorrent and streaming playlist) according to a video * Fetch files (web videos and streaming playlist) according to a video
* *
*/ */
@ -25,8 +25,8 @@ export class VideoFileQueryBuilder extends AbstractVideoQueryBuilder {
super(sequelize, 'get') super(sequelize, 'get')
} }
queryWebTorrentVideos (options: FileQueryOptions) { queryWebVideos (options: FileQueryOptions) {
this.buildWebtorrentFilesQuery(options) this.buildWebVideoFilesQuery(options)
return this.runQuery(options) return this.runQuery(options)
} }
@ -37,15 +37,15 @@ export class VideoFileQueryBuilder extends AbstractVideoQueryBuilder {
return this.runQuery(options) return this.runQuery(options)
} }
private buildWebtorrentFilesQuery (options: FileQueryOptions) { private buildWebVideoFilesQuery (options: FileQueryOptions) {
this.attributes = { this.attributes = {
'"video"."id"': '' '"video"."id"': ''
} }
this.includeWebtorrentFiles() this.includeWebVideoFiles()
if (options.includeRedundancy) { if (options.includeRedundancy) {
this.includeWebTorrentRedundancies() this.includeWebVideoRedundancies()
} }
this.whereId(options) this.whereId(options)

View File

@ -60,10 +60,10 @@ export class VideoModelBuilder {
buildVideosFromRows (options: { buildVideosFromRows (options: {
rows: SQLRow[] rows: SQLRow[]
include?: VideoInclude include?: VideoInclude
rowsWebTorrentFiles?: SQLRow[] rowsWebVideoFiles?: SQLRow[]
rowsStreamingPlaylist?: SQLRow[] rowsStreamingPlaylist?: SQLRow[]
}) { }) {
const { rows, rowsWebTorrentFiles, rowsStreamingPlaylist, include } = options const { rows, rowsWebVideoFiles, rowsStreamingPlaylist, include } = options
this.reinit() this.reinit()
@ -85,8 +85,8 @@ export class VideoModelBuilder {
this.addActorAvatar(row, 'VideoChannel.Account.Actor', accountActor) this.addActorAvatar(row, 'VideoChannel.Account.Actor', accountActor)
} }
if (!rowsWebTorrentFiles) { if (!rowsWebVideoFiles) {
this.addWebTorrentFile(row, videoModel) this.addWebVideoFile(row, videoModel)
} }
if (!rowsStreamingPlaylist) { if (!rowsStreamingPlaylist) {
@ -112,7 +112,7 @@ export class VideoModelBuilder {
} }
} }
this.grabSeparateWebTorrentFiles(rowsWebTorrentFiles) this.grabSeparateWebVideoFiles(rowsWebVideoFiles)
this.grabSeparateStreamingPlaylistFiles(rowsStreamingPlaylist) this.grabSeparateStreamingPlaylistFiles(rowsStreamingPlaylist)
return this.videos return this.videos
@ -140,15 +140,15 @@ export class VideoModelBuilder {
this.videos = [] this.videos = []
} }
private grabSeparateWebTorrentFiles (rowsWebTorrentFiles?: SQLRow[]) { private grabSeparateWebVideoFiles (rowsWebVideoFiles?: SQLRow[]) {
if (!rowsWebTorrentFiles) return if (!rowsWebVideoFiles) return
for (const row of rowsWebTorrentFiles) { for (const row of rowsWebVideoFiles) {
const id = row['VideoFiles.id'] const id = row['VideoFiles.id']
if (!id) continue if (!id) continue
const videoModel = this.videosMemo[row.id] const videoModel = this.videosMemo[row.id]
this.addWebTorrentFile(row, videoModel) this.addWebVideoFile(row, videoModel)
this.addRedundancy(row, 'VideoFiles', this.videoFileMemo[id]) this.addRedundancy(row, 'VideoFiles', this.videoFileMemo[id])
} }
} }
@ -258,7 +258,7 @@ export class VideoModelBuilder {
this.thumbnailsDone.add(id) this.thumbnailsDone.add(id)
} }
private addWebTorrentFile (row: SQLRow, videoModel: VideoModel) { private addWebVideoFile (row: SQLRow, videoModel: VideoModel) {
const id = row['VideoFiles.id'] const id = row['VideoFiles.id']
if (!id || this.videoFileMemo[id]) return if (!id || this.videoFileMemo[id]) return

View File

@ -35,7 +35,7 @@ export type BuildVideoGetQueryOptions = {
export class VideoModelGetQueryBuilder { export class VideoModelGetQueryBuilder {
videoQueryBuilder: VideosModelGetQuerySubBuilder videoQueryBuilder: VideosModelGetQuerySubBuilder
webtorrentFilesQueryBuilder: VideoFileQueryBuilder webVideoFilesQueryBuilder: VideoFileQueryBuilder
streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder
private readonly videoModelBuilder: VideoModelBuilder private readonly videoModelBuilder: VideoModelBuilder
@ -44,7 +44,7 @@ export class VideoModelGetQueryBuilder {
constructor (protected readonly sequelize: Sequelize) { constructor (protected readonly sequelize: Sequelize) {
this.videoQueryBuilder = new VideosModelGetQuerySubBuilder(sequelize) this.videoQueryBuilder = new VideosModelGetQuerySubBuilder(sequelize)
this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) this.webVideoFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
this.videoModelBuilder = new VideoModelBuilder('get', new VideoTableAttributes('get')) this.videoModelBuilder = new VideoModelBuilder('get', new VideoTableAttributes('get'))
@ -57,11 +57,11 @@ export class VideoModelGetQueryBuilder {
includeRedundancy: this.shouldIncludeRedundancies(options) includeRedundancy: this.shouldIncludeRedundancies(options)
} }
const [ videoRows, webtorrentFilesRows, streamingPlaylistFilesRows ] = await Promise.all([ const [ videoRows, webVideoFilesRows, streamingPlaylistFilesRows ] = await Promise.all([
this.videoQueryBuilder.queryVideos(options), this.videoQueryBuilder.queryVideos(options),
VideoModelGetQueryBuilder.videoFilesInclude.has(options.type) VideoModelGetQueryBuilder.videoFilesInclude.has(options.type)
? this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(fileQueryOptions) ? this.webVideoFilesQueryBuilder.queryWebVideos(fileQueryOptions)
: Promise.resolve(undefined), : Promise.resolve(undefined),
VideoModelGetQueryBuilder.videoFilesInclude.has(options.type) VideoModelGetQueryBuilder.videoFilesInclude.has(options.type)
@ -71,7 +71,7 @@ export class VideoModelGetQueryBuilder {
const videos = this.videoModelBuilder.buildVideosFromRows({ const videos = this.videoModelBuilder.buildVideosFromRows({
rows: videoRows, rows: videoRows,
rowsWebTorrentFiles: webtorrentFilesRows, rowsWebVideoFiles: webVideoFilesRows,
rowsStreamingPlaylist: streamingPlaylistFilesRows rowsStreamingPlaylist: streamingPlaylistFilesRows
}) })
@ -92,7 +92,7 @@ export class VideoModelGetQueryBuilder {
export class VideosModelGetQuerySubBuilder extends AbstractVideoQueryBuilder { export class VideosModelGetQuerySubBuilder extends AbstractVideoQueryBuilder {
protected attributes: { [key: string]: string } protected attributes: { [key: string]: string }
protected webtorrentFilesQuery: string protected webVideoFilesQuery: string
protected streamingPlaylistFilesQuery: string protected streamingPlaylistFilesQuery: string
private static readonly trackersInclude = new Set<GetType>([ 'api' ]) private static readonly trackersInclude = new Set<GetType>([ 'api' ])

View File

@ -48,7 +48,9 @@ export type BuildVideosListQueryOptions = {
hasFiles?: boolean hasFiles?: boolean
hasHLSFiles?: boolean hasHLSFiles?: boolean
hasWebtorrentFiles?: boolean
hasWebVideoFiles?: boolean
hasWebtorrentFiles?: boolean // TODO: Remove in v7
accountId?: number accountId?: number
videoChannelId?: number videoChannelId?: number
@ -175,7 +177,9 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
} }
if (exists(options.hasWebtorrentFiles)) { if (exists(options.hasWebtorrentFiles)) {
this.whereWebTorrentFileExists(options.hasWebtorrentFiles) this.whereWebVideoFileExists(options.hasWebtorrentFiles)
} else if (exists(options.hasWebVideoFiles)) {
this.whereWebVideoFileExists(options.hasWebVideoFiles)
} }
if (exists(options.hasHLSFiles)) { if (exists(options.hasHLSFiles)) {
@ -400,18 +404,18 @@ export class VideosIdListQueryBuilder extends AbstractRunQuery {
} }
private whereFileExists () { private whereFileExists () {
this.and.push(`(${this.buildWebTorrentFileExistsQuery(true)} OR ${this.buildHLSFileExistsQuery(true)})`) this.and.push(`(${this.buildWebVideoFileExistsQuery(true)} OR ${this.buildHLSFileExistsQuery(true)})`)
} }
private whereWebTorrentFileExists (exists: boolean) { private whereWebVideoFileExists (exists: boolean) {
this.and.push(this.buildWebTorrentFileExistsQuery(exists)) this.and.push(this.buildWebVideoFileExistsQuery(exists))
} }
private whereHLSFileExists (exists: boolean) { private whereHLSFileExists (exists: boolean) {
this.and.push(this.buildHLSFileExistsQuery(exists)) this.and.push(this.buildHLSFileExistsQuery(exists))
} }
private buildWebTorrentFileExistsQuery (exists: boolean) { private buildWebVideoFileExistsQuery (exists: boolean) {
const prefix = exists ? '' : 'NOT ' const prefix = exists ? '' : 'NOT '
return prefix + 'EXISTS (SELECT 1 FROM "videoFile" WHERE "videoFile"."videoId" = "video"."id")' return prefix + 'EXISTS (SELECT 1 FROM "videoFile" WHERE "videoFile"."videoId" = "video"."id")'

View File

@ -18,7 +18,7 @@ export class VideosModelListQueryBuilder extends AbstractVideoQueryBuilder {
private innerQuery: string private innerQuery: string
private innerSort: string private innerSort: string
webtorrentFilesQueryBuilder: VideoFileQueryBuilder webVideoFilesQueryBuilder: VideoFileQueryBuilder
streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder streamingPlaylistFilesQueryBuilder: VideoFileQueryBuilder
private readonly videoModelBuilder: VideoModelBuilder private readonly videoModelBuilder: VideoModelBuilder
@ -27,7 +27,7 @@ export class VideosModelListQueryBuilder extends AbstractVideoQueryBuilder {
super(sequelize, 'list') super(sequelize, 'list')
this.videoModelBuilder = new VideoModelBuilder(this.mode, this.tables) this.videoModelBuilder = new VideoModelBuilder(this.mode, this.tables)
this.webtorrentFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) this.webVideoFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize) this.streamingPlaylistFilesQueryBuilder = new VideoFileQueryBuilder(sequelize)
} }
@ -48,12 +48,12 @@ export class VideosModelListQueryBuilder extends AbstractVideoQueryBuilder {
includeRedundancy: false includeRedundancy: false
} }
const [ rowsWebTorrentFiles, rowsStreamingPlaylist ] = await Promise.all([ const [ rowsWebVideoFiles, rowsStreamingPlaylist ] = await Promise.all([
this.webtorrentFilesQueryBuilder.queryWebTorrentVideos(fileQueryOptions), this.webVideoFilesQueryBuilder.queryWebVideos(fileQueryOptions),
this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(fileQueryOptions) this.streamingPlaylistFilesQueryBuilder.queryStreamingPlaylistVideos(fileQueryOptions)
]) ])
return this.videoModelBuilder.buildVideosFromRows({ rows, include: options.include, rowsStreamingPlaylist, rowsWebTorrentFiles }) return this.videoModelBuilder.buildVideosFromRows({ rows, include: options.include, rowsStreamingPlaylist, rowsWebVideoFiles })
} }
} }

View File

@ -45,7 +45,7 @@ enum ScopeNames {
{ {
model: VideoModel.scope([ model: VideoModel.scope([
VideoScopeNames.WITH_THUMBNAILS, VideoScopeNames.WITH_THUMBNAILS,
VideoScopeNames.WITH_WEBTORRENT_FILES, VideoScopeNames.WITH_WEB_VIDEO_FILES,
VideoScopeNames.WITH_STREAMING_PLAYLISTS, VideoScopeNames.WITH_STREAMING_PLAYLISTS,
VideoScopeNames.WITH_ACCOUNT_DETAILS VideoScopeNames.WITH_ACCOUNT_DETAILS
]), ]),

View File

@ -26,8 +26,8 @@ import { buildRemoteVideoBaseUrl } from '@server/lib/activitypub/url'
import { import {
getHLSPrivateFileUrl, getHLSPrivateFileUrl,
getHLSPublicFileUrl, getHLSPublicFileUrl,
getWebTorrentPrivateFileUrl, getWebVideoPrivateFileUrl,
getWebTorrentPublicFileUrl getWebVideoPublicFileUrl
} from '@server/lib/object-storage' } from '@server/lib/object-storage'
import { getFSTorrentFilePath } from '@server/lib/paths' import { getFSTorrentFilePath } from '@server/lib/paths'
import { isVideoInPrivateDirectory } from '@server/lib/video-privacy' import { isVideoInPrivateDirectory } from '@server/lib/video-privacy'
@ -276,15 +276,15 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
static async doesOwnedTorrentFileExist (filename: string) { static async doesOwnedTorrentFileExist (filename: string) {
const query = 'SELECT 1 FROM "videoFile" ' + const query = 'SELECT 1 FROM "videoFile" ' +
'LEFT JOIN "video" "webtorrent" ON "webtorrent"."id" = "videoFile"."videoId" AND "webtorrent"."remote" IS FALSE ' + 'LEFT JOIN "video" "webvideo" ON "webvideo"."id" = "videoFile"."videoId" AND "webvideo"."remote" IS FALSE ' +
'LEFT JOIN "videoStreamingPlaylist" ON "videoStreamingPlaylist"."id" = "videoFile"."videoStreamingPlaylistId" ' + 'LEFT JOIN "videoStreamingPlaylist" ON "videoStreamingPlaylist"."id" = "videoFile"."videoStreamingPlaylistId" ' +
'LEFT JOIN "video" "hlsVideo" ON "hlsVideo"."id" = "videoStreamingPlaylist"."videoId" AND "hlsVideo"."remote" IS FALSE ' + 'LEFT JOIN "video" "hlsVideo" ON "hlsVideo"."id" = "videoStreamingPlaylist"."videoId" AND "hlsVideo"."remote" IS FALSE ' +
'WHERE "torrentFilename" = $filename AND ("hlsVideo"."id" IS NOT NULL OR "webtorrent"."id" IS NOT NULL) LIMIT 1' 'WHERE "torrentFilename" = $filename AND ("hlsVideo"."id" IS NOT NULL OR "webvideo"."id" IS NOT NULL) LIMIT 1'
return doesExist(this.sequelize, query, { filename }) return doesExist(this.sequelize, query, { filename })
} }
static async doesOwnedWebTorrentVideoFileExist (filename: string) { static async doesOwnedWebVideoFileExist (filename: string) {
const query = 'SELECT 1 FROM "videoFile" INNER JOIN "video" ON "video"."id" = "videoFile"."videoId" AND "video"."remote" IS FALSE ' + const query = 'SELECT 1 FROM "videoFile" INNER JOIN "video" ON "video"."id" = "videoFile"."videoId" AND "video"."remote" IS FALSE ' +
`WHERE "filename" = $filename AND "storage" = ${VideoStorage.FILE_SYSTEM} LIMIT 1` `WHERE "filename" = $filename AND "storage" = ${VideoStorage.FILE_SYSTEM} LIMIT 1`
@ -378,7 +378,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
} }
static getStats () { static getStats () {
const webtorrentFilesQuery: FindOptions = { const webVideoFilesQuery: FindOptions = {
include: [ include: [
{ {
attributes: [], attributes: [],
@ -412,10 +412,10 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
} }
return Promise.all([ return Promise.all([
VideoFileModel.aggregate('size', 'SUM', webtorrentFilesQuery), VideoFileModel.aggregate('size', 'SUM', webVideoFilesQuery),
VideoFileModel.aggregate('size', 'SUM', hlsFilesQuery) VideoFileModel.aggregate('size', 'SUM', hlsFilesQuery)
]).then(([ webtorrentResult, hlsResult ]) => ({ ]).then(([ webVideoResult, hlsResult ]) => ({
totalLocalVideoFilesSize: parseAggregateResult(webtorrentResult) + parseAggregateResult(hlsResult) totalLocalVideoFilesSize: parseAggregateResult(webVideoResult) + parseAggregateResult(hlsResult)
})) }))
} }
@ -433,7 +433,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
const element = mode === 'streaming-playlist' const element = mode === 'streaming-playlist'
? await VideoFileModel.loadHLSFile({ ...baseFind, playlistId: videoFile.videoStreamingPlaylistId }) ? await VideoFileModel.loadHLSFile({ ...baseFind, playlistId: videoFile.videoStreamingPlaylistId })
: await VideoFileModel.loadWebTorrentFile({ ...baseFind, videoId: videoFile.videoId }) : await VideoFileModel.loadWebVideoFile({ ...baseFind, videoId: videoFile.videoId })
if (!element) return videoFile.save({ transaction }) if (!element) return videoFile.save({ transaction })
@ -444,7 +444,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
return element.save({ transaction }) return element.save({ transaction })
} }
static async loadWebTorrentFile (options: { static async loadWebVideoFile (options: {
videoId: number videoId: number
fps: number fps: number
resolution: number resolution: number
@ -523,7 +523,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
return getHLSPrivateFileUrl(video, this.filename) return getHLSPrivateFileUrl(video, this.filename)
} }
return getWebTorrentPrivateFileUrl(this.filename) return getWebVideoPrivateFileUrl(this.filename)
} }
private getPublicObjectStorageUrl () { private getPublicObjectStorageUrl () {
@ -531,7 +531,7 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
return getHLSPublicFileUrl(this.fileUrl) return getHLSPublicFileUrl(this.fileUrl)
} }
return getWebTorrentPublicFileUrl(this.fileUrl) return getWebVideoPublicFileUrl(this.fileUrl)
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -553,10 +553,10 @@ export class VideoFileModel extends Model<Partial<AttributesOnly<VideoFileModel>
getFileStaticPath (video: MVideo) { getFileStaticPath (video: MVideo) {
if (this.isHLS()) return this.getHLSFileStaticPath(video) if (this.isHLS()) return this.getHLSFileStaticPath(video)
return this.getWebTorrentFileStaticPath(video) return this.getWebVideoFileStaticPath(video)
} }
private getWebTorrentFileStaticPath (video: MVideo) { private getWebVideoFileStaticPath (video: MVideo) {
if (isVideoInPrivateDirectory(video.privacy)) { if (isVideoInPrivateDirectory(video.privacy)) {
return join(STATIC_PATHS.PRIVATE_WEBSEED, this.filename) return join(STATIC_PATHS.PRIVATE_WEBSEED, this.filename)
} }

View File

@ -29,7 +29,7 @@ import {
import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video' import { getPrivaciesForFederation, isPrivacyForFederation, isStateForFederation } from '@server/helpers/video'
import { InternalEventEmitter } from '@server/lib/internal-event-emitter' import { InternalEventEmitter } from '@server/lib/internal-event-emitter'
import { LiveManager } from '@server/lib/live/live-manager' import { LiveManager } from '@server/lib/live/live-manager'
import { removeHLSFileObjectStorageByFilename, removeHLSObjectStorage, removeWebTorrentObjectStorage } from '@server/lib/object-storage' import { removeHLSFileObjectStorageByFilename, removeHLSObjectStorage, removeWebVideoObjectStorage } from '@server/lib/object-storage'
import { tracer } from '@server/lib/opentelemetry/tracing' import { tracer } from '@server/lib/opentelemetry/tracing'
import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths' import { getHLSDirectory, getHLSRedundancyDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths'
import { Hooks } from '@server/lib/plugins/hooks' import { Hooks } from '@server/lib/plugins/hooks'
@ -151,7 +151,7 @@ export enum ScopeNames {
FOR_API = 'FOR_API', FOR_API = 'FOR_API',
WITH_ACCOUNT_DETAILS = 'WITH_ACCOUNT_DETAILS', WITH_ACCOUNT_DETAILS = 'WITH_ACCOUNT_DETAILS',
WITH_TAGS = 'WITH_TAGS', WITH_TAGS = 'WITH_TAGS',
WITH_WEBTORRENT_FILES = 'WITH_WEBTORRENT_FILES', WITH_WEB_VIDEO_FILES = 'WITH_WEB_VIDEO_FILES',
WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE', WITH_SCHEDULED_UPDATE = 'WITH_SCHEDULED_UPDATE',
WITH_BLACKLISTED = 'WITH_BLACKLISTED', WITH_BLACKLISTED = 'WITH_BLACKLISTED',
WITH_STREAMING_PLAYLISTS = 'WITH_STREAMING_PLAYLISTS', WITH_STREAMING_PLAYLISTS = 'WITH_STREAMING_PLAYLISTS',
@ -290,7 +290,7 @@ export type ForAPIOptions = {
} }
] ]
}, },
[ScopeNames.WITH_WEBTORRENT_FILES]: (withRedundancies = false) => { [ScopeNames.WITH_WEB_VIDEO_FILES]: (withRedundancies = false) => {
let subInclude: any[] = [] let subInclude: any[] = []
if (withRedundancies === true) { if (withRedundancies === true) {
@ -813,7 +813,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
// Remove physical files and torrents // Remove physical files and torrents
instance.VideoFiles.forEach(file => { instance.VideoFiles.forEach(file => {
tasks.push(instance.removeWebTorrentFile(file)) tasks.push(instance.removeWebVideoFile(file))
}) })
// Remove playlists file // Remove playlists file
@ -1107,7 +1107,10 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
include?: VideoInclude include?: VideoInclude
hasFiles?: boolean // default false hasFiles?: boolean // default false
hasWebtorrentFiles?: boolean
hasWebtorrentFiles?: boolean // TODO: remove in v7
hasWebVideoFiles?: boolean
hasHLSFiles?: boolean hasHLSFiles?: boolean
categoryOneOf?: number[] categoryOneOf?: number[]
@ -1172,6 +1175,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
'historyOfUser', 'historyOfUser',
'hasHLSFiles', 'hasHLSFiles',
'hasWebtorrentFiles', 'hasWebtorrentFiles',
'hasWebVideoFiles',
'search', 'search',
'excludeAlreadyWatched' 'excludeAlreadyWatched'
]), ]),
@ -1205,7 +1209,9 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
user?: MUserAccountId user?: MUserAccountId
hasWebtorrentFiles?: boolean hasWebtorrentFiles?: boolean // TODO: remove in v7
hasWebVideoFiles?: boolean
hasHLSFiles?: boolean hasHLSFiles?: boolean
search?: string search?: string
@ -1252,6 +1258,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
'durationMax', 'durationMax',
'hasHLSFiles', 'hasHLSFiles',
'hasWebtorrentFiles', 'hasWebtorrentFiles',
'hasWebVideoFiles',
'uuids', 'uuids',
'search', 'search',
'displayOnlyForFollower', 'displayOnlyForFollower',
@ -1676,7 +1683,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
return this.getQualityFileBy(minBy) return this.getQualityFileBy(minBy)
} }
getWebTorrentFile<T extends MVideoWithFile> (this: T, resolution: number): MVideoFileVideo { getWebVideoFile<T extends MVideoWithFile> (this: T, resolution: number): MVideoFileVideo {
if (Array.isArray(this.VideoFiles) === false) return undefined if (Array.isArray(this.VideoFiles) === false) return undefined
const file = this.VideoFiles.find(f => f.resolution === resolution) const file = this.VideoFiles.find(f => f.resolution === resolution)
@ -1685,7 +1692,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
return Object.assign(file, { Video: this }) return Object.assign(file, { Video: this })
} }
hasWebTorrentFiles () { hasWebVideoFiles () {
return Array.isArray(this.VideoFiles) === true && this.VideoFiles.length !== 0 return Array.isArray(this.VideoFiles) === true && this.VideoFiles.length !== 0
} }
@ -1884,7 +1891,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
.concat(toAdd) .concat(toAdd)
} }
removeWebTorrentFile (videoFile: MVideoFile, isRedundancy = false) { removeWebVideoFile (videoFile: MVideoFile, isRedundancy = false) {
const filePath = isRedundancy const filePath = isRedundancy
? VideoPathManager.Instance.getFSRedundancyVideoFilePath(this, videoFile) ? VideoPathManager.Instance.getFSRedundancyVideoFilePath(this, videoFile)
: VideoPathManager.Instance.getFSVideoFileOutputPath(this, videoFile) : VideoPathManager.Instance.getFSVideoFileOutputPath(this, videoFile)
@ -1893,7 +1900,7 @@ export class VideoModel extends Model<Partial<AttributesOnly<VideoModel>>> {
if (!isRedundancy) promises.push(videoFile.removeTorrent()) if (!isRedundancy) promises.push(videoFile.removeTorrent())
if (videoFile.storage === VideoStorage.OBJECT_STORAGE) { if (videoFile.storage === VideoStorage.OBJECT_STORAGE) {
promises.push(removeWebTorrentObjectStorage(videoFile)) promises.push(removeWebVideoObjectStorage(videoFile))
} }
return Promise.all(promises) return Promise.all(promises)

View File

@ -345,7 +345,7 @@ describe('Test config API validators', function () {
}) })
}) })
it('Should fail with a disabled webtorrent & hls transcoding', async function () { it('Should fail with a disabled web videos & hls transcoding', async function () {
const newUpdateParams = { const newUpdateParams = {
...updateParams, ...updateParams,

View File

@ -49,21 +49,21 @@ describe('Test transcoding API validators', function () {
it('Should not run transcoding of a unknown video', async function () { it('Should not run transcoding of a unknown video', async function () {
await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'hls', expectedStatus: HttpStatusCode.NOT_FOUND_404 }) await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'hls', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'webtorrent', expectedStatus: HttpStatusCode.NOT_FOUND_404 }) await servers[0].videos.runTranscoding({ videoId: 404, transcodingType: 'web-video', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}) })
it('Should not run transcoding of a remote video', async function () { it('Should not run transcoding of a remote video', async function () {
const expectedStatus = HttpStatusCode.BAD_REQUEST_400 const expectedStatus = HttpStatusCode.BAD_REQUEST_400
await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'hls', expectedStatus }) await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'hls', expectedStatus })
await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'webtorrent', expectedStatus }) await servers[0].videos.runTranscoding({ videoId: remoteId, transcodingType: 'web-video', expectedStatus })
}) })
it('Should not run transcoding by a non admin user', async function () { it('Should not run transcoding by a non admin user', async function () {
const expectedStatus = HttpStatusCode.FORBIDDEN_403 const expectedStatus = HttpStatusCode.FORBIDDEN_403
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', token: userToken, expectedStatus }) await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', token: userToken, expectedStatus })
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', token: moderatorToken, expectedStatus }) await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', token: moderatorToken, expectedStatus })
}) })
it('Should not run transcoding without transcoding type', async function () { it('Should not run transcoding without transcoding type', async function () {
@ -82,7 +82,7 @@ describe('Test transcoding API validators', function () {
await servers[0].config.disableTranscoding() await servers[0].config.disableTranscoding()
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', expectedStatus }) await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls', expectedStatus })
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', expectedStatus }) await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', expectedStatus })
}) })
it('Should run transcoding', async function () { it('Should run transcoding', async function () {
@ -93,15 +93,15 @@ describe('Test transcoding API validators', function () {
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls' }) await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'hls' })
await waitJobs(servers) await waitJobs(servers)
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent' }) await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video' })
await waitJobs(servers) await waitJobs(servers)
}) })
it('Should not run transcoding on a video that is already being transcoded', async function () { it('Should not run transcoding on a video that is already being transcoded', async function () {
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent' }) await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video' })
const expectedStatus = HttpStatusCode.CONFLICT_409 const expectedStatus = HttpStatusCode.CONFLICT_409
await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'webtorrent', expectedStatus }) await servers[0].videos.runTranscoding({ videoId: validId, transcodingType: 'web-video', expectedStatus })
}) })
after(async function () { after(async function () {

View File

@ -60,7 +60,7 @@ describe('Test videos files', function () {
}) })
describe('Deleting files', function () { describe('Deleting files', function () {
let webtorrentId: string let webVideoId: string
let hlsId: string let hlsId: string
let remoteId: string let remoteId: string
@ -68,10 +68,10 @@ describe('Test videos files', function () {
let validId2: string let validId2: string
let hlsFileId: number let hlsFileId: number
let webtorrentFileId: number let webVideoFileId: number
let remoteHLSFileId: number let remoteHLSFileId: number
let remoteWebtorrentFileId: number let remoteWebVideoFileId: number
before(async function () { before(async function () {
this.timeout(300_000) this.timeout(300_000)
@ -83,7 +83,7 @@ describe('Test videos files', function () {
const video = await servers[1].videos.get({ id: uuid }) const video = await servers[1].videos.get({ id: uuid })
remoteId = video.uuid remoteId = video.uuid
remoteHLSFileId = video.streamingPlaylists[0].files[0].id remoteHLSFileId = video.streamingPlaylists[0].files[0].id
remoteWebtorrentFileId = video.files[0].id remoteWebVideoFileId = video.files[0].id
} }
{ {
@ -96,7 +96,7 @@ describe('Test videos files', function () {
const video = await servers[0].videos.get({ id: uuid }) const video = await servers[0].videos.get({ id: uuid })
validId1 = video.uuid validId1 = video.uuid
hlsFileId = video.streamingPlaylists[0].files[0].id hlsFileId = video.streamingPlaylists[0].files[0].id
webtorrentFileId = video.files[0].id webVideoFileId = video.files[0].id
} }
{ {
@ -117,8 +117,8 @@ describe('Test videos files', function () {
{ {
await servers[0].config.enableTranscoding(false, true) await servers[0].config.enableTranscoding(false, true)
const { uuid } = await servers[0].videos.quickUpload({ name: 'webtorrent' }) const { uuid } = await servers[0].videos.quickUpload({ name: 'web-video' })
webtorrentId = uuid webVideoId = uuid
} }
await waitJobs(servers) await waitJobs(servers)
@ -128,27 +128,27 @@ describe('Test videos files', function () {
const expectedStatus = HttpStatusCode.NOT_FOUND_404 const expectedStatus = HttpStatusCode.NOT_FOUND_404
await servers[0].videos.removeHLSPlaylist({ videoId: 404, expectedStatus }) await servers[0].videos.removeHLSPlaylist({ videoId: 404, expectedStatus })
await servers[0].videos.removeAllWebTorrentFiles({ videoId: 404, expectedStatus }) await servers[0].videos.removeAllWebVideoFiles({ videoId: 404, expectedStatus })
await servers[0].videos.removeHLSFile({ videoId: 404, fileId: hlsFileId, expectedStatus }) await servers[0].videos.removeHLSFile({ videoId: 404, fileId: hlsFileId, expectedStatus })
await servers[0].videos.removeWebTorrentFile({ videoId: 404, fileId: webtorrentFileId, expectedStatus }) await servers[0].videos.removeWebVideoFile({ videoId: 404, fileId: webVideoFileId, expectedStatus })
}) })
it('Should not delete unknown files', async function () { it('Should not delete unknown files', async function () {
const expectedStatus = HttpStatusCode.NOT_FOUND_404 const expectedStatus = HttpStatusCode.NOT_FOUND_404
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: webtorrentFileId, expectedStatus }) await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: webVideoFileId, expectedStatus })
await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: hlsFileId, expectedStatus }) await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: hlsFileId, expectedStatus })
}) })
it('Should not delete files of a remote video', async function () { it('Should not delete files of a remote video', async function () {
const expectedStatus = HttpStatusCode.BAD_REQUEST_400 const expectedStatus = HttpStatusCode.BAD_REQUEST_400
await servers[0].videos.removeHLSPlaylist({ videoId: remoteId, expectedStatus }) await servers[0].videos.removeHLSPlaylist({ videoId: remoteId, expectedStatus })
await servers[0].videos.removeAllWebTorrentFiles({ videoId: remoteId, expectedStatus }) await servers[0].videos.removeAllWebVideoFiles({ videoId: remoteId, expectedStatus })
await servers[0].videos.removeHLSFile({ videoId: remoteId, fileId: remoteHLSFileId, expectedStatus }) await servers[0].videos.removeHLSFile({ videoId: remoteId, fileId: remoteHLSFileId, expectedStatus })
await servers[0].videos.removeWebTorrentFile({ videoId: remoteId, fileId: remoteWebtorrentFileId, expectedStatus }) await servers[0].videos.removeWebVideoFile({ videoId: remoteId, fileId: remoteWebVideoFileId, expectedStatus })
}) })
it('Should not delete files by a non admin user', async function () { it('Should not delete files by a non admin user', async function () {
@ -157,35 +157,35 @@ describe('Test videos files', function () {
await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: userToken, expectedStatus }) await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: userToken, expectedStatus })
await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: moderatorToken, expectedStatus }) await servers[0].videos.removeHLSPlaylist({ videoId: validId1, token: moderatorToken, expectedStatus })
await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1, token: userToken, expectedStatus }) await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1, token: userToken, expectedStatus })
await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1, token: moderatorToken, expectedStatus }) await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1, token: moderatorToken, expectedStatus })
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: userToken, expectedStatus }) await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: userToken, expectedStatus })
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: moderatorToken, expectedStatus }) await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId, token: moderatorToken, expectedStatus })
await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId, token: userToken, expectedStatus }) await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId, token: userToken, expectedStatus })
await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId, token: moderatorToken, expectedStatus }) await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId, token: moderatorToken, expectedStatus })
}) })
it('Should not delete files if the files are not available', async function () { it('Should not delete files if the files are not available', async function () {
await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
await servers[0].videos.removeAllWebTorrentFiles({ videoId: webtorrentId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) await servers[0].videos.removeAllWebVideoFiles({ videoId: webVideoId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
await servers[0].videos.removeHLSFile({ videoId: hlsId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) await servers[0].videos.removeHLSFile({ videoId: hlsId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 }) await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: 404, expectedStatus: HttpStatusCode.NOT_FOUND_404 })
}) })
it('Should not delete files if no both versions are available', async function () { it('Should not delete files if no both versions are available', async function () {
await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) await servers[0].videos.removeHLSPlaylist({ videoId: hlsId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
await servers[0].videos.removeAllWebTorrentFiles({ videoId: webtorrentId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 }) await servers[0].videos.removeAllWebVideoFiles({ videoId: webVideoId, expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
}) })
it('Should delete files if both versions are available', async function () { it('Should delete files if both versions are available', async function () {
await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId }) await servers[0].videos.removeHLSFile({ videoId: validId1, fileId: hlsFileId })
await servers[0].videos.removeWebTorrentFile({ videoId: validId1, fileId: webtorrentFileId }) await servers[0].videos.removeWebVideoFile({ videoId: validId1, fileId: webVideoFileId })
await servers[0].videos.removeHLSPlaylist({ videoId: validId1 }) await servers[0].videos.removeHLSPlaylist({ videoId: validId1 })
await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId2 }) await servers[0].videos.removeAllWebVideoFiles({ videoId: validId2 })
}) })
}) })

View File

@ -120,7 +120,7 @@ describe('Object storage for video static file privacy', function () {
const video = await server.videos.getWithToken({ id: videoId }) const video = await server.videos.getWithToken({ id: videoId })
return { return {
webTorrentFile: video.files[0].fileUrl, webVideoFile: video.files[0].fileUrl,
hlsFile: getHLS(video).files[0].fileUrl hlsFile: getHLS(video).files[0].fileUrl
} }
} }
@ -175,10 +175,10 @@ describe('Object storage for video static file privacy', function () {
it('Should not get files without appropriate OAuth token', async function () { it('Should not get files without appropriate OAuth token', async function () {
this.timeout(60000) this.timeout(60000)
const { webTorrentFile, hlsFile } = await getSampleFileUrls(privateVideoUUID) const { webVideoFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
await makeRawRequest({ url: webTorrentFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) await makeRawRequest({ url: webVideoFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
await makeRawRequest({ url: webTorrentFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) await makeRawRequest({ url: webVideoFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
await makeRawRequest({ url: hlsFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) await makeRawRequest({ url: hlsFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
await makeRawRequest({ url: hlsFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) await makeRawRequest({ url: hlsFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
@ -187,18 +187,18 @@ describe('Object storage for video static file privacy', function () {
it('Should not get files without appropriate password or appropriate OAuth token', async function () { it('Should not get files without appropriate password or appropriate OAuth token', async function () {
this.timeout(60000) this.timeout(60000)
const { webTorrentFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID) const { webVideoFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID)
await makeRawRequest({ url: webTorrentFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) await makeRawRequest({ url: webVideoFile, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
await makeRawRequest({ await makeRawRequest({
url: webTorrentFile, url: webVideoFile,
token: null, token: null,
headers: incorrectPasswordHeader, headers: incorrectPasswordHeader,
expectedStatus: HttpStatusCode.FORBIDDEN_403 expectedStatus: HttpStatusCode.FORBIDDEN_403
}) })
await makeRawRequest({ url: webTorrentFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) await makeRawRequest({ url: webVideoFile, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
await makeRawRequest({ await makeRawRequest({
url: webTorrentFile, url: webVideoFile,
token: null, token: null,
headers: correctPasswordHeader, headers: correctPasswordHeader,
expectedStatus: HttpStatusCode.OK_200 expectedStatus: HttpStatusCode.OK_200
@ -239,9 +239,9 @@ describe('Object storage for video static file privacy', function () {
const badVideoFileToken = await server.videoToken.getVideoFileToken({ token: userToken, videoId: userPrivateVideoUUID }) const badVideoFileToken = await server.videoToken.getVideoFileToken({ token: userToken, videoId: userPrivateVideoUUID })
const goodVideoFileToken = await server.videoToken.getVideoFileToken({ videoId: privateVideoUUID }) const goodVideoFileToken = await server.videoToken.getVideoFileToken({ videoId: privateVideoUUID })
const { webTorrentFile, hlsFile } = await getSampleFileUrls(privateVideoUUID) const { webVideoFile, hlsFile } = await getSampleFileUrls(privateVideoUUID)
for (const url of [ webTorrentFile, hlsFile ]) { for (const url of [ webVideoFile, hlsFile ]) {
await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
@ -261,9 +261,9 @@ describe('Object storage for video static file privacy', function () {
videoPassword: correctPassword videoPassword: correctPassword
}) })
const { webTorrentFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID) const { webVideoFile, hlsFile } = await getSampleFileUrls(passwordProtectedVideoUUID)
for (const url of [ hlsFile, webTorrentFile ]) { for (const url of [ hlsFile, webVideoFile ]) {
await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) await makeRawRequest({ url, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 }) await makeRawRequest({ url, token: userToken, expectedStatus: HttpStatusCode.FORBIDDEN_403 })
await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 }) await makeRawRequest({ url, token: server.accessToken, expectedStatus: HttpStatusCode.OK_200 })
@ -534,11 +534,11 @@ describe('Object storage for video static file privacy', function () {
it('Should not be able to access object storage proxy', async function () { it('Should not be able to access object storage proxy', async function () {
const privateVideo = await server.videos.getWithToken({ id: videoUUID }) const privateVideo = await server.videos.getWithToken({ id: videoUUID })
const webtorrentFilename = extractFilenameFromUrl(privateVideo.files[0].fileUrl) const webVideoFilename = extractFilenameFromUrl(privateVideo.files[0].fileUrl)
const hlsFilename = extractFilenameFromUrl(getHLS(privateVideo).files[0].fileUrl) const hlsFilename = extractFilenameFromUrl(getHLS(privateVideo).files[0].fileUrl)
await makeRawRequest({ await makeRawRequest({
url: server.url + '/object-storage-proxy/webseed/private/' + webtorrentFilename, url: server.url + '/object-storage-proxy/webseed/private/' + webVideoFilename,
token: server.accessToken, token: server.accessToken,
expectedStatus: HttpStatusCode.BAD_REQUEST_400 expectedStatus: HttpStatusCode.BAD_REQUEST_400
}) })

View File

@ -41,8 +41,8 @@ async function checkFiles (options: {
playlistBucket: string playlistBucket: string
playlistPrefix?: string playlistPrefix?: string
webtorrentBucket: string webVideoBucket: string
webtorrentPrefix?: string webVideoPrefix?: string
}) { }) {
const { const {
server, server,
@ -50,20 +50,20 @@ async function checkFiles (options: {
originSQLCommand, originSQLCommand,
video, video,
playlistBucket, playlistBucket,
webtorrentBucket, webVideoBucket,
baseMockUrl, baseMockUrl,
playlistPrefix, playlistPrefix,
webtorrentPrefix webVideoPrefix
} = options } = options
let allFiles = video.files let allFiles = video.files
for (const file of video.files) { for (const file of video.files) {
const baseUrl = baseMockUrl const baseUrl = baseMockUrl
? `${baseMockUrl}/${webtorrentBucket}/` ? `${baseMockUrl}/${webVideoBucket}/`
: `http://${webtorrentBucket}.${ObjectStorageCommand.getMockEndpointHost()}/` : `http://${webVideoBucket}.${ObjectStorageCommand.getMockEndpointHost()}/`
const prefix = webtorrentPrefix || '' const prefix = webVideoPrefix || ''
const start = baseUrl + prefix const start = baseUrl + prefix
expectStartWith(file.fileUrl, start) expectStartWith(file.fileUrl, start)
@ -134,8 +134,8 @@ function runTestSuite (options: {
playlistBucket: string playlistBucket: string
playlistPrefix?: string playlistPrefix?: string
webtorrentBucket: string webVideoBucket: string
webtorrentPrefix?: string webVideoPrefix?: string
useMockBaseUrl?: boolean useMockBaseUrl?: boolean
}) { }) {
@ -161,7 +161,7 @@ function runTestSuite (options: {
: undefined : undefined
await objectStorage.createMockBucket(options.playlistBucket) await objectStorage.createMockBucket(options.playlistBucket)
await objectStorage.createMockBucket(options.webtorrentBucket) await objectStorage.createMockBucket(options.webVideoBucket)
const config = { const config = {
object_storage: { object_storage: {
@ -182,10 +182,10 @@ function runTestSuite (options: {
}, },
videos: { videos: {
bucket_name: options.webtorrentBucket, bucket_name: options.webVideoBucket,
prefix: options.webtorrentPrefix, prefix: options.webVideoPrefix,
base_url: baseMockUrl base_url: baseMockUrl
? `${baseMockUrl}/${options.webtorrentBucket}` ? `${baseMockUrl}/${options.webVideoBucket}`
: undefined : undefined
} }
} }
@ -386,27 +386,27 @@ describe('Object storage for videos', function () {
describe('Test simple object storage', function () { describe('Test simple object storage', function () {
runTestSuite({ runTestSuite({
playlistBucket: objectStorage.getMockBucketName('streaming-playlists'), playlistBucket: objectStorage.getMockBucketName('streaming-playlists'),
webtorrentBucket: objectStorage.getMockBucketName('videos') webVideoBucket: objectStorage.getMockBucketName('videos')
}) })
}) })
describe('Test object storage with prefix', function () { describe('Test object storage with prefix', function () {
runTestSuite({ runTestSuite({
playlistBucket: objectStorage.getMockBucketName('mybucket'), playlistBucket: objectStorage.getMockBucketName('mybucket'),
webtorrentBucket: objectStorage.getMockBucketName('mybucket'), webVideoBucket: objectStorage.getMockBucketName('mybucket'),
playlistPrefix: 'streaming-playlists_', playlistPrefix: 'streaming-playlists_',
webtorrentPrefix: 'webtorrent_' webVideoPrefix: 'webvideo_'
}) })
}) })
describe('Test object storage with prefix and base URL', function () { describe('Test object storage with prefix and base URL', function () {
runTestSuite({ runTestSuite({
playlistBucket: objectStorage.getMockBucketName('mybucket'), playlistBucket: objectStorage.getMockBucketName('mybucket'),
webtorrentBucket: objectStorage.getMockBucketName('mybucket'), webVideoBucket: objectStorage.getMockBucketName('mybucket'),
playlistPrefix: 'streaming-playlists/', playlistPrefix: 'streaming-playlists/',
webtorrentPrefix: 'webtorrent/', webVideoPrefix: 'webvideo/',
useMockBaseUrl: true useMockBaseUrl: true
}) })
@ -431,7 +431,7 @@ describe('Object storage for videos', function () {
runTestSuite({ runTestSuite({
maxUploadPart, maxUploadPart,
playlistBucket: objectStorage.getMockBucketName('streaming-playlists'), playlistBucket: objectStorage.getMockBucketName('streaming-playlists'),
webtorrentBucket: objectStorage.getMockBucketName('videos'), webVideoBucket: objectStorage.getMockBucketName('videos'),
fixture fixture
}) })
}) })

View File

@ -43,7 +43,7 @@ async function checkMagnetWebseeds (file: VideoFile, baseWebseeds: string[], ser
} }
} }
async function createServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) { async function createServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebVideo = true) {
const strategies: any[] = [] const strategies: any[] = []
if (strategy !== null) { if (strategy !== null) {
@ -61,7 +61,7 @@ async function createServers (strategy: VideoRedundancyStrategy | null, addition
const config = { const config = {
transcoding: { transcoding: {
webtorrent: { webtorrent: {
enabled: withWebtorrent enabled: withWebVideo
}, },
hls: { hls: {
enabled: true enabled: true
@ -100,7 +100,7 @@ async function createServers (strategy: VideoRedundancyStrategy | null, addition
} }
async function ensureSameFilenames (videoUUID: string) { async function ensureSameFilenames (videoUUID: string) {
let webtorrentFilenames: string[] let webVideoFilenames: string[]
let hlsFilenames: string[] let hlsFilenames: string[]
for (const server of servers) { for (const server of servers) {
@ -108,17 +108,17 @@ async function ensureSameFilenames (videoUUID: string) {
// Ensure we use the same filenames that the origin // Ensure we use the same filenames that the origin
const localWebtorrentFilenames = video.files.map(f => basename(f.fileUrl)).sort() const localWebVideoFilenames = video.files.map(f => basename(f.fileUrl)).sort()
const localHLSFilenames = video.streamingPlaylists[0].files.map(f => basename(f.fileUrl)).sort() const localHLSFilenames = video.streamingPlaylists[0].files.map(f => basename(f.fileUrl)).sort()
if (webtorrentFilenames) expect(webtorrentFilenames).to.deep.equal(localWebtorrentFilenames) if (webVideoFilenames) expect(webVideoFilenames).to.deep.equal(localWebVideoFilenames)
else webtorrentFilenames = localWebtorrentFilenames else webVideoFilenames = localWebVideoFilenames
if (hlsFilenames) expect(hlsFilenames).to.deep.equal(localHLSFilenames) if (hlsFilenames) expect(hlsFilenames).to.deep.equal(localHLSFilenames)
else hlsFilenames = localHLSFilenames else hlsFilenames = localHLSFilenames
} }
return { webtorrentFilenames, hlsFilenames } return { webVideoFilenames, hlsFilenames }
} }
async function check1WebSeed (videoUUID?: string) { async function check1WebSeed (videoUUID?: string) {
@ -156,7 +156,7 @@ async function check2Webseeds (videoUUID?: string) {
} }
} }
const { webtorrentFilenames } = await ensureSameFilenames(videoUUID) const { webVideoFilenames } = await ensureSameFilenames(videoUUID)
const directories = [ const directories = [
servers[0].getDirectoryPath('redundancy'), servers[0].getDirectoryPath('redundancy'),
@ -168,7 +168,7 @@ async function check2Webseeds (videoUUID?: string) {
expect(files).to.have.length.at.least(4) expect(files).to.have.length.at.least(4)
// Ensure we files exist on disk // Ensure we files exist on disk
expect(files.find(f => webtorrentFilenames.includes(f))).to.exist expect(files.find(f => webVideoFilenames.includes(f))).to.exist
} }
} }

View File

@ -14,7 +14,7 @@ import {
describe('Test audio only video transcoding', function () { describe('Test audio only video transcoding', function () {
let servers: PeerTubeServer[] = [] let servers: PeerTubeServer[] = []
let videoUUID: string let videoUUID: string
let webtorrentAudioFileUrl: string let webVideoAudioFileUrl: string
let fragmentedAudioFileUrl: string let fragmentedAudioFileUrl: string
before(async function () { before(async function () {
@ -71,7 +71,7 @@ describe('Test audio only video transcoding', function () {
} }
if (server.serverNumber === 1) { if (server.serverNumber === 1) {
webtorrentAudioFileUrl = video.files[2].fileUrl webVideoAudioFileUrl = video.files[2].fileUrl
fragmentedAudioFileUrl = video.streamingPlaylists[0].files[2].fileUrl fragmentedAudioFileUrl = video.streamingPlaylists[0].files[2].fileUrl
} }
} }
@ -79,7 +79,7 @@ describe('Test audio only video transcoding', function () {
it('0p transcoded video should not have video', async function () { it('0p transcoded video should not have video', async function () {
const paths = [ const paths = [
servers[0].servers.buildWebTorrentFilePath(webtorrentAudioFileUrl), servers[0].servers.buildWebVideoFilePath(webVideoAudioFileUrl),
servers[0].servers.buildFragmentedFilePath(videoUUID, fragmentedAudioFileUrl) servers[0].servers.buildFragmentedFilePath(videoUUID, fragmentedAudioFileUrl)
] ]

View File

@ -96,12 +96,12 @@ function runTests (enableObjectStorage: boolean) {
} }
}) })
it('Should generate WebTorrent', async function () { it('Should generate Web Video', async function () {
this.timeout(60000) this.timeout(60000)
await servers[0].videos.runTranscoding({ await servers[0].videos.runTranscoding({
videoId: videoUUID, videoId: videoUUID,
transcodingType: 'webtorrent' transcodingType: 'web-video'
}) })
await waitJobs(servers) await waitJobs(servers)
@ -117,13 +117,13 @@ function runTests (enableObjectStorage: boolean) {
} }
}) })
it('Should generate WebTorrent from HLS only video', async function () { it('Should generate Web Video from HLS only video', async function () {
this.timeout(60000) this.timeout(60000)
await servers[0].videos.removeAllWebTorrentFiles({ videoId: videoUUID }) await servers[0].videos.removeAllWebVideoFiles({ videoId: videoUUID })
await waitJobs(servers) await waitJobs(servers)
await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'webtorrent' }) await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'web-video' })
await waitJobs(servers) await waitJobs(servers)
for (const server of servers) { for (const server of servers) {
@ -137,13 +137,13 @@ function runTests (enableObjectStorage: boolean) {
} }
}) })
it('Should only generate WebTorrent', async function () { it('Should only generate Web Video', async function () {
this.timeout(60000) this.timeout(60000)
await servers[0].videos.removeHLSPlaylist({ videoId: videoUUID }) await servers[0].videos.removeHLSPlaylist({ videoId: videoUUID })
await waitJobs(servers) await waitJobs(servers)
await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'webtorrent' }) await servers[0].videos.runTranscoding({ videoId: videoUUID, transcodingType: 'web-video' })
await waitJobs(servers) await waitJobs(servers)
for (const server of servers) { for (const server of servers) {

View File

@ -111,7 +111,7 @@ describe('Test HLS videos', function () {
await doubleFollow(servers[0], servers[1]) await doubleFollow(servers[0], servers[1])
}) })
describe('With WebTorrent & HLS enabled', function () { describe('With Web Video & HLS enabled', function () {
runTestSuite(false) runTestSuite(false)
}) })

View File

@ -251,7 +251,7 @@ describe('Test video transcoding', function () {
expect(videoDetails.files).to.have.lengthOf(5) expect(videoDetails.files).to.have.lengthOf(5)
const file = videoDetails.files.find(f => f.resolution.id === 240) const file = videoDetails.files.find(f => f.resolution.id === 240)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const probe = await getAudioStream(path) const probe = await getAudioStream(path)
if (probe.audioStream) { if (probe.audioStream) {
@ -281,7 +281,7 @@ describe('Test video transcoding', function () {
const videoDetails = await server.videos.get({ id: video.id }) const videoDetails = await server.videos.get({ id: video.id })
const file = videoDetails.files.find(f => f.resolution.id === 240) const file = videoDetails.files.find(f => f.resolution.id === 240)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
expect(await hasAudioStream(path)).to.be.false expect(await hasAudioStream(path)).to.be.false
} }
@ -310,7 +310,7 @@ describe('Test video transcoding', function () {
const fixtureVideoProbe = await getAudioStream(fixturePath) const fixtureVideoProbe = await getAudioStream(fixturePath)
const file = videoDetails.files.find(f => f.resolution.id === 240) const file = videoDetails.files.find(f => f.resolution.id === 240)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const videoProbe = await getAudioStream(path) const videoProbe = await getAudioStream(path)
@ -472,14 +472,14 @@ describe('Test video transcoding', function () {
for (const resolution of [ 144, 240, 360, 480 ]) { for (const resolution of [ 144, 240, 360, 480 ]) {
const file = videoDetails.files.find(f => f.resolution.id === resolution) const file = videoDetails.files.find(f => f.resolution.id === resolution)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const fps = await getVideoStreamFPS(path) const fps = await getVideoStreamFPS(path)
expect(fps).to.be.below(31) expect(fps).to.be.below(31)
} }
const file = videoDetails.files.find(f => f.resolution.id === 720) const file = videoDetails.files.find(f => f.resolution.id === 720)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const fps = await getVideoStreamFPS(path) const fps = await getVideoStreamFPS(path)
expect(fps).to.be.above(58).and.below(62) expect(fps).to.be.above(58).and.below(62)
@ -516,14 +516,14 @@ describe('Test video transcoding', function () {
{ {
const file = video.files.find(f => f.resolution.id === 240) const file = video.files.find(f => f.resolution.id === 240)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const fps = await getVideoStreamFPS(path) const fps = await getVideoStreamFPS(path)
expect(fps).to.be.equal(25) expect(fps).to.be.equal(25)
} }
{ {
const file = video.files.find(f => f.resolution.id === 720) const file = video.files.find(f => f.resolution.id === 720)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const fps = await getVideoStreamFPS(path) const fps = await getVideoStreamFPS(path)
expect(fps).to.be.equal(59) expect(fps).to.be.equal(59)
} }
@ -556,7 +556,7 @@ describe('Test video transcoding', function () {
for (const resolution of [ 240, 360, 480, 720, 1080 ]) { for (const resolution of [ 240, 360, 480, 720, 1080 ]) {
const file = video.files.find(f => f.resolution.id === resolution) const file = video.files.find(f => f.resolution.id === resolution)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const bitrate = await getVideoStreamBitrate(path) const bitrate = await getVideoStreamBitrate(path)
const fps = await getVideoStreamFPS(path) const fps = await getVideoStreamFPS(path)
@ -607,7 +607,7 @@ describe('Test video transcoding', function () {
for (const r of resolutions) { for (const r of resolutions) {
const file = video.files.find(f => f.resolution.id === r) const file = video.files.find(f => f.resolution.id === r)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const bitrate = await getVideoStreamBitrate(path) const bitrate = await getVideoStreamBitrate(path)
const inputBitrate = 60_000 const inputBitrate = 60_000
@ -631,7 +631,7 @@ describe('Test video transcoding', function () {
{ {
const video = await servers[1].videos.get({ id: videoUUID }) const video = await servers[1].videos.get({ id: videoUUID })
const file = video.files.find(f => f.resolution.id === 240) const file = video.files.find(f => f.resolution.id === 240)
const path = servers[1].servers.buildWebTorrentFilePath(file.fileUrl) const path = servers[1].servers.buildWebVideoFilePath(file.fileUrl)
const probe = await ffprobePromise(path) const probe = await ffprobePromise(path)
const metadata = new VideoFileMetadata(probe) const metadata = new VideoFileMetadata(probe)
@ -704,14 +704,14 @@ describe('Test video transcoding', function () {
expect(transcodingJobs).to.have.lengthOf(16) expect(transcodingJobs).to.have.lengthOf(16)
const hlsJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-hls') const hlsJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-hls')
const webtorrentJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-webtorrent') const webVideoJobs = transcodingJobs.filter(j => j.data.type === 'new-resolution-to-web-video')
const optimizeJobs = transcodingJobs.filter(j => j.data.type === 'optimize-to-webtorrent') const optimizeJobs = transcodingJobs.filter(j => j.data.type === 'optimize-to-web-video')
expect(hlsJobs).to.have.lengthOf(8) expect(hlsJobs).to.have.lengthOf(8)
expect(webtorrentJobs).to.have.lengthOf(7) expect(webVideoJobs).to.have.lengthOf(7)
expect(optimizeJobs).to.have.lengthOf(1) expect(optimizeJobs).to.have.lengthOf(1)
for (const j of optimizeJobs.concat(hlsJobs.concat(webtorrentJobs))) { for (const j of optimizeJobs.concat(hlsJobs.concat(webVideoJobs))) {
expect(j.priority).to.be.greaterThan(100) expect(j.priority).to.be.greaterThan(100)
expect(j.priority).to.be.lessThan(150) expect(j.priority).to.be.lessThan(150)
} }

View File

@ -96,7 +96,7 @@ describe('Test update video privacy while transcoding', function () {
await doubleFollow(servers[0], servers[1]) await doubleFollow(servers[0], servers[1])
}) })
describe('With WebTorrent & HLS enabled', function () { describe('With Web Video & HLS enabled', function () {
runTestSuite(false) runTestSuite(false)
}) })

View File

@ -273,7 +273,7 @@ describe('Test video studio', function () {
describe('HLS only studio edition', function () { describe('HLS only studio edition', function () {
before(async function () { before(async function () {
// Disable webtorrent // Disable Web Videos
await servers[0].config.updateExistingSubConfig({ await servers[0].config.updateExistingSubConfig({
newConfig: { newConfig: {
transcoding: { transcoding: {
@ -354,8 +354,8 @@ describe('Test video studio', function () {
expect(oldFileUrls).to.not.include(f.fileUrl) expect(oldFileUrls).to.not.include(f.fileUrl)
} }
for (const webtorrentFile of video.files) { for (const webVideoFile of video.files) {
expectStartWith(webtorrentFile.fileUrl, objectStorage.getMockWebVideosBaseUrl()) expectStartWith(webVideoFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
} }
for (const hlsFile of video.streamingPlaylists[0].files) { for (const hlsFile of video.streamingPlaylists[0].files) {

View File

@ -184,7 +184,7 @@ describe('Test user videos', function () {
} }
}) })
it('Should disable webtorrent, enable HLS, and update my quota', async function () { it('Should disable web videos, enable HLS, and update my quota', async function () {
this.timeout(160000) this.timeout(160000)
{ {

View File

@ -229,25 +229,13 @@ describe('Test users', function () {
}) })
it('Should be able to change the p2p attribute', async function () { it('Should be able to change the p2p attribute', async function () {
{ await server.users.updateMe({
await server.users.updateMe({ token: userToken,
token: userToken, p2pEnabled: true
webTorrentEnabled: false })
})
const user = await server.users.getMyInfo({ token: userToken }) const user = await server.users.getMyInfo({ token: userToken })
expect(user.p2pEnabled).to.be.false expect(user.p2pEnabled).to.be.true
}
{
await server.users.updateMe({
token: userToken,
p2pEnabled: true
})
const user = await server.users.getMyInfo({ token: userToken })
expect(user.p2pEnabled).to.be.true
}
}) })
it('Should be able to change the email attribute', async function () { it('Should be able to change the email attribute', async function () {

View File

@ -48,10 +48,10 @@ describe('Test videos files', function () {
await waitJobs(servers) await waitJobs(servers)
}) })
it('Should delete webtorrent files', async function () { it('Should delete web video files', async function () {
this.timeout(30_000) this.timeout(30_000)
await servers[0].videos.removeAllWebTorrentFiles({ videoId: validId1 }) await servers[0].videos.removeAllWebVideoFiles({ videoId: validId1 })
await waitJobs(servers) await waitJobs(servers)
@ -80,15 +80,15 @@ describe('Test videos files', function () {
}) })
describe('When deleting a specific file', function () { describe('When deleting a specific file', function () {
let webtorrentId: string let webVideoId: string
let hlsId: string let hlsId: string
before(async function () { before(async function () {
this.timeout(120_000) this.timeout(120_000)
{ {
const { uuid } = await servers[0].videos.quickUpload({ name: 'webtorrent' }) const { uuid } = await servers[0].videos.quickUpload({ name: 'web-video' })
webtorrentId = uuid webVideoId = uuid
} }
{ {
@ -99,38 +99,38 @@ describe('Test videos files', function () {
await waitJobs(servers) await waitJobs(servers)
}) })
it('Shoulde delete a webtorrent file', async function () { it('Shoulde delete a web video file', async function () {
this.timeout(30_000) this.timeout(30_000)
const video = await servers[0].videos.get({ id: webtorrentId }) const video = await servers[0].videos.get({ id: webVideoId })
const files = video.files const files = video.files
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentId, fileId: files[0].id }) await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: files[0].id })
await waitJobs(servers) await waitJobs(servers)
for (const server of servers) { for (const server of servers) {
const video = await server.videos.get({ id: webtorrentId }) const video = await server.videos.get({ id: webVideoId })
expect(video.files).to.have.lengthOf(files.length - 1) expect(video.files).to.have.lengthOf(files.length - 1)
expect(video.files.find(f => f.id === files[0].id)).to.not.exist expect(video.files.find(f => f.id === files[0].id)).to.not.exist
} }
}) })
it('Should delete all webtorrent files', async function () { it('Should delete all web video files', async function () {
this.timeout(30_000) this.timeout(30_000)
const video = await servers[0].videos.get({ id: webtorrentId }) const video = await servers[0].videos.get({ id: webVideoId })
const files = video.files const files = video.files
for (const file of files) { for (const file of files) {
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentId, fileId: file.id }) await servers[0].videos.removeWebVideoFile({ videoId: webVideoId, fileId: file.id })
} }
await waitJobs(servers) await waitJobs(servers)
for (const server of servers) { for (const server of servers) {
const video = await server.videos.get({ id: webtorrentId }) const video = await server.videos.get({ id: webVideoId })
expect(video.files).to.have.lengthOf(0) expect(video.files).to.have.lengthOf(0)
} }
@ -182,16 +182,16 @@ describe('Test videos files', function () {
it('Should not delete last file of a video', async function () { it('Should not delete last file of a video', async function () {
this.timeout(60_000) this.timeout(60_000)
const webtorrentOnly = await servers[0].videos.get({ id: hlsId }) const webVideoOnly = await servers[0].videos.get({ id: hlsId })
const hlsOnly = await servers[0].videos.get({ id: webtorrentId }) const hlsOnly = await servers[0].videos.get({ id: webVideoId })
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentOnly.id, fileId: webtorrentOnly.files[i].id }) await servers[0].videos.removeWebVideoFile({ videoId: webVideoOnly.id, fileId: webVideoOnly.files[i].id })
await servers[0].videos.removeHLSFile({ videoId: hlsOnly.id, fileId: hlsOnly.streamingPlaylists[0].files[i].id }) await servers[0].videos.removeHLSFile({ videoId: hlsOnly.id, fileId: hlsOnly.streamingPlaylists[0].files[i].id })
} }
const expectedStatus = HttpStatusCode.BAD_REQUEST_400 const expectedStatus = HttpStatusCode.BAD_REQUEST_400
await servers[0].videos.removeWebTorrentFile({ videoId: webtorrentOnly.id, fileId: webtorrentOnly.files[4].id, expectedStatus }) await servers[0].videos.removeWebVideoFile({ videoId: webVideoOnly.id, fileId: webVideoOnly.files[4].id, expectedStatus })
await servers[0].videos.removeHLSFile({ videoId: hlsOnly.id, fileId: hlsOnly.streamingPlaylists[0].files[4].id, expectedStatus }) await servers[0].videos.removeHLSFile({ videoId: hlsOnly.id, fileId: hlsOnly.streamingPlaylists[0].files[4].id, expectedStatus })
}) })
}) })

View File

@ -154,7 +154,7 @@ describe('Test videos filter', function () {
server: PeerTubeServer server: PeerTubeServer
path: string path: string
isLocal?: boolean isLocal?: boolean
hasWebtorrentFiles?: boolean hasWebVideoFiles?: boolean
hasHLSFiles?: boolean hasHLSFiles?: boolean
include?: VideoInclude include?: VideoInclude
privacyOneOf?: VideoPrivacy[] privacyOneOf?: VideoPrivacy[]
@ -174,7 +174,7 @@ describe('Test videos filter', function () {
'include', 'include',
'category', 'category',
'tagsAllOf', 'tagsAllOf',
'hasWebtorrentFiles', 'hasWebVideoFiles',
'hasHLSFiles', 'hasHLSFiles',
'privacyOneOf', 'privacyOneOf',
'excludeAlreadyWatched' 'excludeAlreadyWatched'
@ -463,14 +463,14 @@ describe('Test videos filter', function () {
} }
}) })
it('Should filter by HLS or WebTorrent files', async function () { it('Should filter by HLS or Web Video files', async function () {
this.timeout(360000) this.timeout(360000)
const finderFactory = (name: string) => (videos: Video[]) => videos.some(v => v.name === name) const finderFactory = (name: string) => (videos: Video[]) => videos.some(v => v.name === name)
await servers[0].config.enableTranscoding(true, false) await servers[0].config.enableTranscoding(true, false)
await servers[0].videos.upload({ attributes: { name: 'webtorrent video' } }) await servers[0].videos.upload({ attributes: { name: 'web video video' } })
const hasWebtorrent = finderFactory('webtorrent video') const hasWebVideo = finderFactory('web video video')
await waitJobs(servers) await waitJobs(servers)
@ -481,24 +481,24 @@ describe('Test videos filter', function () {
await waitJobs(servers) await waitJobs(servers)
await servers[0].config.enableTranscoding(true, true) await servers[0].config.enableTranscoding(true, true)
await servers[0].videos.upload({ attributes: { name: 'hls and webtorrent video' } }) await servers[0].videos.upload({ attributes: { name: 'hls and web video video' } })
const hasBoth = finderFactory('hls and webtorrent video') const hasBoth = finderFactory('hls and web video video')
await waitJobs(servers) await waitJobs(servers)
for (const path of paths) { for (const path of paths) {
{ {
const videos = await listVideos({ server: servers[0], path, hasWebtorrentFiles: true }) const videos = await listVideos({ server: servers[0], path, hasWebVideoFiles: true })
expect(hasWebtorrent(videos)).to.be.true expect(hasWebVideo(videos)).to.be.true
expect(hasHLS(videos)).to.be.false expect(hasHLS(videos)).to.be.false
expect(hasBoth(videos)).to.be.true expect(hasBoth(videos)).to.be.true
} }
{ {
const videos = await listVideos({ server: servers[0], path, hasWebtorrentFiles: false }) const videos = await listVideos({ server: servers[0], path, hasWebVideoFiles: false })
expect(hasWebtorrent(videos)).to.be.false expect(hasWebVideo(videos)).to.be.false
expect(hasHLS(videos)).to.be.true expect(hasHLS(videos)).to.be.true
expect(hasBoth(videos)).to.be.false expect(hasBoth(videos)).to.be.false
} }
@ -506,7 +506,7 @@ describe('Test videos filter', function () {
{ {
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true }) const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true })
expect(hasWebtorrent(videos)).to.be.false expect(hasWebVideo(videos)).to.be.false
expect(hasHLS(videos)).to.be.true expect(hasHLS(videos)).to.be.true
expect(hasBoth(videos)).to.be.true expect(hasBoth(videos)).to.be.true
} }
@ -514,23 +514,23 @@ describe('Test videos filter', function () {
{ {
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false }) const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false })
expect(hasWebtorrent(videos)).to.be.true expect(hasWebVideo(videos)).to.be.true
expect(hasHLS(videos)).to.be.false expect(hasHLS(videos)).to.be.false
expect(hasBoth(videos)).to.be.false expect(hasBoth(videos)).to.be.false
} }
{ {
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false, hasWebtorrentFiles: false }) const videos = await listVideos({ server: servers[0], path, hasHLSFiles: false, hasWebVideoFiles: false })
expect(hasWebtorrent(videos)).to.be.false expect(hasWebVideo(videos)).to.be.false
expect(hasHLS(videos)).to.be.false expect(hasHLS(videos)).to.be.false
expect(hasBoth(videos)).to.be.false expect(hasBoth(videos)).to.be.false
} }
{ {
const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true, hasWebtorrentFiles: true }) const videos = await listVideos({ server: servers[0], path, hasHLSFiles: true, hasWebVideoFiles: true })
expect(hasWebtorrent(videos)).to.be.false expect(hasWebVideo(videos)).to.be.false
expect(hasHLS(videos)).to.be.false expect(hasHLS(videos)).to.be.false
expect(hasBoth(videos)).to.be.true expect(hasBoth(videos)).to.be.true
} }

View File

@ -44,8 +44,8 @@ describe('Test studio transcoding in peertube-runner program', function () {
} }
if (objectStorage) { if (objectStorage) {
for (const webtorrentFile of video.files) { for (const webVideoFile of video.files) {
expectStartWith(webtorrentFile.fileUrl, objectStorage.getMockWebVideosBaseUrl()) expectStartWith(webVideoFile.fileUrl, objectStorage.getMockWebVideosBaseUrl())
} }
for (const hlsFile of video.streamingPlaylists[0].files) { for (const hlsFile of video.streamingPlaylists[0].files) {

View File

@ -24,13 +24,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
let peertubeRunner: PeerTubeRunnerProcess let peertubeRunner: PeerTubeRunnerProcess
function runSuite (options: { function runSuite (options: {
webtorrentEnabled: boolean webVideoEnabled: boolean
hlsEnabled: boolean hlsEnabled: boolean
objectStorage?: ObjectStorageCommand objectStorage?: ObjectStorageCommand
}) { }) {
const { webtorrentEnabled, hlsEnabled, objectStorage } = options const { webVideoEnabled, hlsEnabled, objectStorage } = options
const objectStorageBaseUrlWebTorrent = objectStorage const objectStorageBaseUrlWebVideo = objectStorage
? objectStorage.getMockWebVideosBaseUrl() ? objectStorage.getMockWebVideosBaseUrl()
: undefined : undefined
@ -46,13 +46,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await waitJobs(servers, { runnerJobs: true }) await waitJobs(servers, { runnerJobs: true })
for (const server of servers) { for (const server of servers) {
if (webtorrentEnabled) { if (webVideoEnabled) {
await completeWebVideoFilesCheck({ await completeWebVideoFilesCheck({
server, server,
originServer: servers[0], originServer: servers[0],
fixture: 'video_short.mp4', fixture: 'video_short.mp4',
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent, objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
files: [ files: [
{ resolution: 0 }, { resolution: 0 },
{ resolution: 144 }, { resolution: 144 },
@ -66,7 +66,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
if (hlsEnabled) { if (hlsEnabled) {
await completeCheckHlsPlaylist({ await completeCheckHlsPlaylist({
hlsOnly: !webtorrentEnabled, hlsOnly: !webVideoEnabled,
servers, servers,
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlHLS, objectStorageBaseUrl: objectStorageBaseUrlHLS,
@ -84,13 +84,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await waitJobs(servers, { runnerJobs: true }) await waitJobs(servers, { runnerJobs: true })
for (const server of servers) { for (const server of servers) {
if (webtorrentEnabled) { if (webVideoEnabled) {
await completeWebVideoFilesCheck({ await completeWebVideoFilesCheck({
server, server,
originServer: servers[0], originServer: servers[0],
fixture: 'video_short.webm', fixture: 'video_short.webm',
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent, objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
files: [ files: [
{ resolution: 0 }, { resolution: 0 },
{ resolution: 144 }, { resolution: 144 },
@ -104,7 +104,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
if (hlsEnabled) { if (hlsEnabled) {
await completeCheckHlsPlaylist({ await completeCheckHlsPlaylist({
hlsOnly: !webtorrentEnabled, hlsOnly: !webVideoEnabled,
servers, servers,
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlHLS, objectStorageBaseUrl: objectStorageBaseUrlHLS,
@ -123,13 +123,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await waitJobs(servers, { runnerJobs: true }) await waitJobs(servers, { runnerJobs: true })
for (const server of servers) { for (const server of servers) {
if (webtorrentEnabled) { if (webVideoEnabled) {
await completeWebVideoFilesCheck({ await completeWebVideoFilesCheck({
server, server,
originServer: servers[0], originServer: servers[0],
fixture: 'sample.ogg', fixture: 'sample.ogg',
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent, objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
files: [ files: [
{ resolution: 0 }, { resolution: 0 },
{ resolution: 144 }, { resolution: 144 },
@ -142,7 +142,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
if (hlsEnabled) { if (hlsEnabled) {
await completeCheckHlsPlaylist({ await completeCheckHlsPlaylist({
hlsOnly: !webtorrentEnabled, hlsOnly: !webVideoEnabled,
servers, servers,
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlHLS, objectStorageBaseUrl: objectStorageBaseUrlHLS,
@ -159,13 +159,13 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await waitJobs(servers, { runnerJobs: true }) await waitJobs(servers, { runnerJobs: true })
if (webtorrentEnabled) { if (webVideoEnabled) {
await completeWebVideoFilesCheck({ await completeWebVideoFilesCheck({
server: servers[0], server: servers[0],
originServer: servers[0], originServer: servers[0],
fixture: 'video_short.mp4', fixture: 'video_short.mp4',
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent, objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
files: [ files: [
{ resolution: 0 }, { resolution: 0 },
{ resolution: 144 }, { resolution: 144 },
@ -179,7 +179,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
if (hlsEnabled) { if (hlsEnabled) {
await completeCheckHlsPlaylist({ await completeCheckHlsPlaylist({
hlsOnly: !webtorrentEnabled, hlsOnly: !webVideoEnabled,
servers: [ servers[0] ], servers: [ servers[0] ],
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlHLS, objectStorageBaseUrl: objectStorageBaseUrlHLS,
@ -203,7 +203,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await servers[0].config.enableTranscoding(true, true, true) await servers[0].config.enableTranscoding(true, true, true)
await servers[0].videos.runTranscoding({ transcodingType: 'webtorrent', videoId: uuid }) await servers[0].videos.runTranscoding({ transcodingType: 'web-video', videoId: uuid })
await waitJobs(servers, { runnerJobs: true }) await waitJobs(servers, { runnerJobs: true })
await completeWebVideoFilesCheck({ await completeWebVideoFilesCheck({
@ -211,7 +211,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
originServer: servers[0], originServer: servers[0],
fixture: 'video_short.mp4', fixture: 'video_short.mp4',
videoUUID: uuid, videoUUID: uuid,
objectStorageBaseUrl: objectStorageBaseUrlWebTorrent, objectStorageBaseUrl: objectStorageBaseUrlWebVideo,
files: [ files: [
{ resolution: 0 }, { resolution: 0 },
{ resolution: 144 }, { resolution: 144 },
@ -262,7 +262,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await servers[0].config.enableTranscoding(true, false, true) await servers[0].config.enableTranscoding(true, false, true)
}) })
runSuite({ webtorrentEnabled: true, hlsEnabled: false }) runSuite({ webVideoEnabled: true, hlsEnabled: false })
}) })
describe('HLS videos only enabled', function () { describe('HLS videos only enabled', function () {
@ -271,7 +271,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await servers[0].config.enableTranscoding(false, true, true) await servers[0].config.enableTranscoding(false, true, true)
}) })
runSuite({ webtorrentEnabled: false, hlsEnabled: true }) runSuite({ webVideoEnabled: false, hlsEnabled: true })
}) })
describe('Web video & HLS enabled', function () { describe('Web video & HLS enabled', function () {
@ -280,7 +280,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await servers[0].config.enableTranscoding(true, true, true) await servers[0].config.enableTranscoding(true, true, true)
}) })
runSuite({ webtorrentEnabled: true, hlsEnabled: true }) runSuite({ webVideoEnabled: true, hlsEnabled: true })
}) })
}) })
@ -306,7 +306,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await servers[0].config.enableTranscoding(true, false, true) await servers[0].config.enableTranscoding(true, false, true)
}) })
runSuite({ webtorrentEnabled: true, hlsEnabled: false, objectStorage }) runSuite({ webVideoEnabled: true, hlsEnabled: false, objectStorage })
}) })
describe('HLS videos only enabled', function () { describe('HLS videos only enabled', function () {
@ -315,7 +315,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await servers[0].config.enableTranscoding(false, true, true) await servers[0].config.enableTranscoding(false, true, true)
}) })
runSuite({ webtorrentEnabled: false, hlsEnabled: true, objectStorage }) runSuite({ webVideoEnabled: false, hlsEnabled: true, objectStorage })
}) })
describe('Web video & HLS enabled', function () { describe('Web video & HLS enabled', function () {
@ -324,7 +324,7 @@ describe('Test VOD transcoding in peertube-runner program', function () {
await servers[0].config.enableTranscoding(true, true, true) await servers[0].config.enableTranscoding(true, true, true)
}) })
runSuite({ webtorrentEnabled: true, hlsEnabled: true, objectStorage }) runSuite({ webVideoEnabled: true, hlsEnabled: true, objectStorage })
}) })
after(async function () { after(async function () {

View File

@ -302,11 +302,11 @@ describe('Test plugin helpers', function () {
// Video files check // Video files check
{ {
expect(body.webtorrent.videoFiles).to.be.an('array') expect(body.webVideo.videoFiles).to.be.an('array')
expect(body.hls.videoFiles).to.be.an('array') expect(body.hls.videoFiles).to.be.an('array')
for (const resolution of [ 144, 240, 360, 480, 720 ]) { for (const resolution of [ 144, 240, 360, 480, 720 ]) {
for (const files of [ body.webtorrent.videoFiles, body.hls.videoFiles ]) { for (const files of [ body.webVideo.videoFiles, body.hls.videoFiles ]) {
const file = files.find(f => f.resolution === resolution) const file = files.find(f => f.resolution === resolution)
expect(file).to.exist expect(file).to.exist
@ -318,7 +318,7 @@ describe('Test plugin helpers', function () {
} }
} }
videoPath = body.webtorrent.videoFiles[0].path videoPath = body.webVideo.videoFiles[0].path
} }
// Thumbnails check // Thumbnails check

View File

@ -247,7 +247,7 @@ describe('Test transcoding plugins', function () {
const video = await server.videos.get({ id: videoUUID }) const video = await server.videos.get({ id: videoUUID })
const path = server.servers.buildWebTorrentFilePath(video.files[0].fileUrl) const path = server.servers.buildWebVideoFilePath(video.files[0].fileUrl)
const audioProbe = await getAudioStream(path) const audioProbe = await getAudioStream(path)
expect(audioProbe.audioStream.codec_name).to.equal('opus') expect(audioProbe.audioStream.codec_name).to.equal('opus')

View File

@ -215,22 +215,22 @@ async function checkVideoFilesWereRemoved (options: {
}) { }) {
const { video, server, captions = [], onlyVideoFiles = false } = options const { video, server, captions = [], onlyVideoFiles = false } = options
const webtorrentFiles = video.files || [] const webVideoFiles = video.files || []
const hlsFiles = video.streamingPlaylists[0]?.files || [] const hlsFiles = video.streamingPlaylists[0]?.files || []
const thumbnailName = basename(video.thumbnailPath) const thumbnailName = basename(video.thumbnailPath)
const previewName = basename(video.previewPath) const previewName = basename(video.previewPath)
const torrentNames = webtorrentFiles.concat(hlsFiles).map(f => basename(f.torrentUrl)) const torrentNames = webVideoFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
const captionNames = captions.map(c => basename(c.captionPath)) const captionNames = captions.map(c => basename(c.captionPath))
const webtorrentFilenames = webtorrentFiles.map(f => basename(f.fileUrl)) const webVideoFilenames = webVideoFiles.map(f => basename(f.fileUrl))
const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl)) const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl))
let directories: { [ directory: string ]: string[] } = { let directories: { [ directory: string ]: string[] } = {
videos: webtorrentFilenames, videos: webVideoFilenames,
redundancy: webtorrentFilenames, redundancy: webVideoFilenames,
[join('playlists', 'hls')]: hlsFilenames, [join('playlists', 'hls')]: hlsFilenames,
[join('redundancy', 'hls')]: hlsFilenames [join('redundancy', 'hls')]: hlsFilenames
} }

View File

@ -65,19 +65,19 @@ async function listRedundanciesCLI (target: VideoRedundanciesTarget) {
}) as any }) as any
for (const redundancy of data) { for (const redundancy of data) {
const webtorrentFiles = redundancy.redundancies.files const webVideoFiles = redundancy.redundancies.files
const streamingPlaylists = redundancy.redundancies.streamingPlaylists const streamingPlaylists = redundancy.redundancies.streamingPlaylists
let totalSize = '' let totalSize = ''
if (target === 'remote-videos') { if (target === 'remote-videos') {
const tmp = webtorrentFiles.concat(streamingPlaylists) const tmp = webVideoFiles.concat(streamingPlaylists)
.reduce((a, b) => a + b.size, 0) .reduce((a, b) => a + b.size, 0)
totalSize = bytes(tmp) totalSize = bytes(tmp)
} }
const instances = uniqify( const instances = uniqify(
webtorrentFiles.concat(streamingPlaylists) webVideoFiles.concat(streamingPlaylists)
.map(r => r.fileUrl) .map(r => r.fileUrl)
.map(u => new URL(u).host) .map(u => new URL(u).host)
) )
@ -86,7 +86,7 @@ async function listRedundanciesCLI (target: VideoRedundanciesTarget) {
redundancy.id.toString(), redundancy.id.toString(),
redundancy.name, redundancy.name,
redundancy.url, redundancy.url,
webtorrentFiles.length, webVideoFiles.length,
streamingPlaylists.length, streamingPlaylists.length,
instances.join('\n'), instances.join('\n'),
totalSize totalSize

View File

@ -38,6 +38,6 @@ export function isStreamingPlaylistFile (file: any): file is MVideoFileStreaming
return !!file.videoStreamingPlaylistId return !!file.videoStreamingPlaylistId
} }
export function isWebtorrentFile (file: any): file is MVideoFileVideo { export function isWebVideoFile (file: any): file is MVideoFileVideo {
return !!file.videoId return !!file.videoId
} }

View File

@ -41,7 +41,17 @@ export type PeerTubeHelpers = {
ffprobe: (path: string) => Promise<any> ffprobe: (path: string) => Promise<any>
getFiles: (id: number | string) => Promise<{ getFiles: (id: number | string) => Promise<{
webtorrent: { webtorrent: { // TODO: remove in v7
videoFiles: {
path: string // Could be null if using remote storage
url: string
resolution: number
size: number
fps: number
}[]
}
webVideo: {
videoFiles: { videoFiles: {
path: string // Could be null if using remote storage path: string // Could be null if using remote storage
url: string url: string

View File

@ -30,7 +30,9 @@ export interface VideosCommonQuery {
tagsAllOf?: string[] tagsAllOf?: string[]
hasHLSFiles?: boolean hasHLSFiles?: boolean
hasWebtorrentFiles?: boolean
hasWebtorrentFiles?: boolean // TODO: remove in v7
hasWebVideoFiles?: boolean
skipCount?: boolean skipCount?: boolean

View File

@ -148,17 +148,17 @@ export interface HLSTranscodingPayload extends BaseTranscodingPayload {
fps: number fps: number
copyCodecs: boolean copyCodecs: boolean
deleteWebTorrentFiles: boolean deleteWebVideoFiles: boolean
} }
export interface NewWebTorrentResolutionTranscodingPayload extends BaseTranscodingPayload { export interface NewWebVideoResolutionTranscodingPayload extends BaseTranscodingPayload {
type: 'new-resolution-to-webtorrent' type: 'new-resolution-to-web-video'
resolution: VideoResolution resolution: VideoResolution
fps: number fps: number
} }
export interface MergeAudioTranscodingPayload extends BaseTranscodingPayload { export interface MergeAudioTranscodingPayload extends BaseTranscodingPayload {
type: 'merge-audio-to-webtorrent' type: 'merge-audio-to-web-video'
resolution: VideoResolution resolution: VideoResolution
fps: number fps: number
@ -167,7 +167,7 @@ export interface MergeAudioTranscodingPayload extends BaseTranscodingPayload {
} }
export interface OptimizeTranscodingPayload extends BaseTranscodingPayload { export interface OptimizeTranscodingPayload extends BaseTranscodingPayload {
type: 'optimize-to-webtorrent' type: 'optimize-to-web-video'
quickTranscode: boolean quickTranscode: boolean
@ -176,7 +176,7 @@ export interface OptimizeTranscodingPayload extends BaseTranscodingPayload {
export type VideoTranscodingPayload = export type VideoTranscodingPayload =
HLSTranscodingPayload HLSTranscodingPayload
| NewWebTorrentResolutionTranscodingPayload | NewWebVideoResolutionTranscodingPayload
| OptimizeTranscodingPayload | OptimizeTranscodingPayload
| MergeAudioTranscodingPayload | MergeAudioTranscodingPayload

View File

@ -5,8 +5,6 @@ export interface UserUpdateMe {
description?: string description?: string
nsfwPolicy?: NSFWPolicyType nsfwPolicy?: NSFWPolicyType
// FIXME: deprecated in favour of p2pEnabled in 4.1
webTorrentEnabled?: boolean
p2pEnabled?: boolean p2pEnabled?: boolean
autoPlayVideo?: boolean autoPlayVideo?: boolean

View File

@ -22,8 +22,6 @@ export interface User {
autoPlayNextVideo: boolean autoPlayNextVideo: boolean
autoPlayNextVideoPlaylist: boolean autoPlayNextVideoPlaylist: boolean
// @deprecated in favour of p2pEnabled
webTorrentEnabled: boolean
p2pEnabled: boolean p2pEnabled: boolean
videosHistoryEnabled: boolean videosHistoryEnabled: boolean

View File

@ -1,3 +1,3 @@
export interface VideoTranscodingCreate { export interface VideoTranscodingCreate {
transcodingType: 'hls' | 'webtorrent' transcodingType: 'hls' | 'webtorrent' | 'web-video' // TODO: remove webtorrent in v7
} }

View File

@ -131,7 +131,7 @@ export class ConfigCommand extends AbstractCommand {
} }
// TODO: convert args to object // TODO: convert args to object
enableTranscoding (webtorrent = true, hls = true, with0p = false) { enableTranscoding (webVideo = true, hls = true, with0p = false) {
return this.updateExistingSubConfig({ return this.updateExistingSubConfig({
newConfig: { newConfig: {
transcoding: { transcoding: {
@ -143,7 +143,7 @@ export class ConfigCommand extends AbstractCommand {
resolutions: ConfigCommand.getCustomConfigResolutions(true, with0p), resolutions: ConfigCommand.getCustomConfigResolutions(true, with0p),
webtorrent: { webtorrent: {
enabled: webtorrent enabled: webVideo
}, },
hls: { hls: {
enabled: hls enabled: hls
@ -154,7 +154,7 @@ export class ConfigCommand extends AbstractCommand {
} }
// TODO: convert args to object // TODO: convert args to object
enableMinimumTranscoding (webtorrent = true, hls = true) { enableMinimumTranscoding (webVideo = true, hls = true) {
return this.updateExistingSubConfig({ return this.updateExistingSubConfig({
newConfig: { newConfig: {
transcoding: { transcoding: {
@ -170,7 +170,7 @@ export class ConfigCommand extends AbstractCommand {
}, },
webtorrent: { webtorrent: {
enabled: webtorrent enabled: webVideo
}, },
hls: { hls: {
enabled: hls enabled: hls

View File

@ -77,7 +77,7 @@ export class ServersCommand extends AbstractCommand {
return join(root(), 'test' + this.server.internalServerNumber, directory) return join(root(), 'test' + this.server.internalServerNumber, directory)
} }
buildWebTorrentFilePath (fileUrl: string) { buildWebVideoFilePath (fileUrl: string) {
return this.buildDirectory(join('videos', basename(fileUrl))) return this.buildDirectory(join('videos', basename(fileUrl)))
} }

View File

@ -686,10 +686,10 @@ export class VideosCommand extends AbstractCommand {
}) })
} }
removeAllWebTorrentFiles (options: OverrideCommandOptions & { removeAllWebVideoFiles (options: OverrideCommandOptions & {
videoId: number | string videoId: number | string
}) { }) {
const path = '/api/v1/videos/' + options.videoId + '/webtorrent' const path = '/api/v1/videos/' + options.videoId + '/web-videos'
return this.deleteRequest({ return this.deleteRequest({
...options, ...options,
@ -700,11 +700,11 @@ export class VideosCommand extends AbstractCommand {
}) })
} }
removeWebTorrentFile (options: OverrideCommandOptions & { removeWebVideoFile (options: OverrideCommandOptions & {
videoId: number | string videoId: number | string
fileId: number fileId: number
}) { }) {
const path = '/api/v1/videos/' + options.videoId + '/webtorrent/' + options.fileId const path = '/api/v1/videos/' + options.videoId + '/web-videos/' + options.fileId
return this.deleteRequest({ return this.deleteRequest({
...options, ...options,
@ -717,7 +717,7 @@ export class VideosCommand extends AbstractCommand {
runTranscoding (options: OverrideCommandOptions & { runTranscoding (options: OverrideCommandOptions & {
videoId: number | string videoId: number | string
transcodingType: 'hls' | 'webtorrent' transcodingType: 'hls' | 'webtorrent' | 'web-video'
}) { }) {
const path = '/api/v1/videos/' + options.videoId + '/transcoding' const path = '/api/v1/videos/' + options.videoId + '/transcoding'

View File

@ -146,7 +146,7 @@ Value must be a valid color (`red` or `rgba(100, 100, 100, 0.5)`).
Force a specific player engine. Force a specific player engine.
Value must be a valid mode (`webtorrent` or `p2p-media-loader`). Value must be a valid mode (`web-video` or `p2p-media-loader`).
### api ### api

Some files were not shown because too many files have changed in this diff Show More