From 57f879a540551c3b958b0991c8e1e3657a4481d8 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 9 Jul 2021 10:21:10 +0200 Subject: Introduce streaming playlists command --- shared/extra-utils/videos/index.ts | 3 +- .../videos/streaming-playlists-command.ts | 45 ++++++++++++ shared/extra-utils/videos/streaming-playlists.ts | 76 ++++++++++++++++++++ .../videos/video-streaming-playlists.ts | 82 ---------------------- 4 files changed, 123 insertions(+), 83 deletions(-) create mode 100644 shared/extra-utils/videos/streaming-playlists-command.ts create mode 100644 shared/extra-utils/videos/streaming-playlists.ts delete mode 100644 shared/extra-utils/videos/video-streaming-playlists.ts (limited to 'shared/extra-utils/videos') diff --git a/shared/extra-utils/videos/index.ts b/shared/extra-utils/videos/index.ts index 372cf7a90..f87ae8eea 100644 --- a/shared/extra-utils/videos/index.ts +++ b/shared/extra-utils/videos/index.ts @@ -9,7 +9,8 @@ export * from './live' export * from './playlists-command' export * from './playlists' export * from './services-command' +export * from './streaming-playlists-command' +export * from './streaming-playlists' export * from './video-channels' export * from './video-comments' -export * from './video-streaming-playlists' export * from './videos' diff --git a/shared/extra-utils/videos/streaming-playlists-command.ts b/shared/extra-utils/videos/streaming-playlists-command.ts new file mode 100644 index 000000000..4caec7137 --- /dev/null +++ b/shared/extra-utils/videos/streaming-playlists-command.ts @@ -0,0 +1,45 @@ + +import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes' +import { unwrapBody, unwrapText } from '../requests' +import { AbstractCommand, OverrideCommandOptions } from '../shared' + +export class StreamingPlaylistsCommand extends AbstractCommand { + + get (options: OverrideCommandOptions & { + url: string + }) { + return unwrapText(this.getRawRequest({ + ...options, + + url: options.url, + implicitToken: false, + defaultExpectedStatus: HttpStatusCode.OK_200 + })) + } + + getSegment (options: OverrideCommandOptions & { + url: string + range?: string + }) { + return unwrapText(this.getRawRequest({ + ...options, + + url: options.url, + range: options.range, + implicitToken: false, + defaultExpectedStatus: HttpStatusCode.OK_200, + })) + } + + getSegmentSha256 (options: OverrideCommandOptions & { + url: string + }) { + return unwrapBody<{ [ id: string ]: string }>(this.getRawRequest({ + ...options, + + url: options.url, + implicitToken: false, + defaultExpectedStatus: HttpStatusCode.OK_200 + })) + } +} diff --git a/shared/extra-utils/videos/streaming-playlists.ts b/shared/extra-utils/videos/streaming-playlists.ts new file mode 100644 index 000000000..0324c739a --- /dev/null +++ b/shared/extra-utils/videos/streaming-playlists.ts @@ -0,0 +1,76 @@ +import { expect } from 'chai' +import { sha256 } from '@server/helpers/core-utils' +import { HttpStatusCode } from '@shared/core-utils' +import { VideoStreamingPlaylist } from '@shared/models' +import { ServerInfo } from '../server' + +async function checkSegmentHash (options: { + server: ServerInfo + baseUrlPlaylist: string + baseUrlSegment: string + videoUUID: string + resolution: number + hlsPlaylist: VideoStreamingPlaylist +}) { + const { server, baseUrlPlaylist, baseUrlSegment, videoUUID, resolution, hlsPlaylist } = options + const command = server.streamingPlaylistsCommand + + const playlist = await command.get({ url: `${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8` }) + + const videoName = `${videoUUID}-${resolution}-fragmented.mp4` + + const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist) + + const length = parseInt(matches[1], 10) + const offset = parseInt(matches[2], 10) + const range = `${offset}-${offset + length - 1}` + + const segmentBody = await command.getSegment({ + url: `${baseUrlSegment}/${videoUUID}/${videoName}`, + expectedStatus: HttpStatusCode.PARTIAL_CONTENT_206, + range: `bytes=${range}` + }) + + const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url }) + expect(sha256(segmentBody)).to.equal(shaBody[videoName][range]) +} + +async function checkLiveSegmentHash (options: { + server: ServerInfo + baseUrlSegment: string + videoUUID: string + segmentName: string + hlsPlaylist: VideoStreamingPlaylist +}) { + const { server, baseUrlSegment, videoUUID, segmentName, hlsPlaylist } = options + const command = server.streamingPlaylistsCommand + + const segmentBody = await command.getSegment({ url: `${baseUrlSegment}/${videoUUID}/${segmentName}` }) + const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url }) + + expect(sha256(segmentBody)).to.equal(shaBody[segmentName]) +} + +async function checkResolutionsInMasterPlaylist (options: { + server: ServerInfo + playlistUrl: string + resolutions: number[] +}) { + const { server, playlistUrl, resolutions } = options + + const masterPlaylist = await server.streamingPlaylistsCommand.get({ url: playlistUrl }) + + for (const resolution of resolutions) { + const reg = new RegExp( + '#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution + ',(FRAME-RATE=\\d+,)?CODECS="avc1.64001f,mp4a.40.2"' + ) + + expect(masterPlaylist).to.match(reg) + } +} + +export { + checkSegmentHash, + checkLiveSegmentHash, + checkResolutionsInMasterPlaylist +} diff --git a/shared/extra-utils/videos/video-streaming-playlists.ts b/shared/extra-utils/videos/video-streaming-playlists.ts deleted file mode 100644 index 99c2e1880..000000000 --- a/shared/extra-utils/videos/video-streaming-playlists.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { makeRawRequest } from '../requests/requests' -import { sha256 } from '../../../server/helpers/core-utils' -import { VideoStreamingPlaylist } from '../../models/videos/video-streaming-playlist.model' -import { expect } from 'chai' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' - -function getPlaylist (url: string, statusCodeExpected = HttpStatusCode.OK_200) { - return makeRawRequest(url, statusCodeExpected) -} - -function getSegment (url: string, statusCodeExpected = HttpStatusCode.OK_200, range?: string) { - return makeRawRequest(url, statusCodeExpected, range) -} - -function getSegmentSha256 (url: string, statusCodeExpected = HttpStatusCode.OK_200) { - return makeRawRequest(url, statusCodeExpected) -} - -async function checkSegmentHash ( - baseUrlPlaylist: string, - baseUrlSegment: string, - videoUUID: string, - resolution: number, - hlsPlaylist: VideoStreamingPlaylist -) { - const res = await getPlaylist(`${baseUrlPlaylist}/${videoUUID}/${resolution}.m3u8`) - const playlist = res.text - - const videoName = `${videoUUID}-${resolution}-fragmented.mp4` - - const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist) - - const length = parseInt(matches[1], 10) - const offset = parseInt(matches[2], 10) - const range = `${offset}-${offset + length - 1}` - - const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${videoName}`, HttpStatusCode.PARTIAL_CONTENT_206, `bytes=${range}`) - - const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url) - - const sha256Server = resSha.body[videoName][range] - expect(sha256(res2.body)).to.equal(sha256Server) -} - -async function checkLiveSegmentHash ( - baseUrlSegment: string, - videoUUID: string, - segmentName: string, - hlsPlaylist: VideoStreamingPlaylist -) { - const res2 = await getSegment(`${baseUrlSegment}/${videoUUID}/${segmentName}`) - - const resSha = await getSegmentSha256(hlsPlaylist.segmentsSha256Url) - - const sha256Server = resSha.body[segmentName] - expect(sha256(res2.body)).to.equal(sha256Server) -} - -async function checkResolutionsInMasterPlaylist (playlistUrl: string, resolutions: number[]) { - const res = await getPlaylist(playlistUrl) - - const masterPlaylist = res.text - - for (const resolution of resolutions) { - const reg = new RegExp( - '#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution + ',(FRAME-RATE=\\d+,)?CODECS="avc1.64001f,mp4a.40.2"' - ) - - expect(masterPlaylist).to.match(reg) - } -} - -// --------------------------------------------------------------------------- - -export { - getPlaylist, - getSegment, - checkResolutionsInMasterPlaylist, - getSegmentSha256, - checkLiveSegmentHash, - checkSegmentHash -} -- cgit v1.2.3