ResultList,
VideoCreateResult,
VideoDetails,
+ VideoPrivacy,
VideoState
} from '@shared/models'
import { unwrapBody } from '../requests'
+import { ObjectStorageCommand, PeerTubeServer } from '../server'
import { AbstractCommand, OverrideCommandOptions } from '../shared'
import { sendRTMPStream, testFfmpegStreamError } from './live'
})
}
+ // ---------------------------------------------------------------------------
+
listSessions (options: OverrideCommandOptions & {
videoId: number | string
}) {
})
}
+ // ---------------------------------------------------------------------------
+
update (options: OverrideCommandOptions & {
videoId: number | string
fields: LiveVideoUpdate
return body.video
}
+ async quickCreate (options: OverrideCommandOptions & {
+ saveReplay: boolean
+ permanentLive: boolean
+ privacy?: VideoPrivacy
+ }) {
+ const { saveReplay, permanentLive, privacy = VideoPrivacy.PUBLIC } = options
+
+ const { uuid } = await this.create({
+ ...options,
+
+ fields: {
+ name: 'live',
+ permanentLive,
+ saveReplay,
+ replaySettings: { privacy },
+ channelId: this.server.store.channel.id,
+ privacy
+ }
+ })
+
+ const video = await this.server.videos.getWithToken({ id: uuid })
+ const live = await this.get({ videoId: uuid })
+
+ return { video, live }
+ }
+
+ // ---------------------------------------------------------------------------
+
async sendRTMPStreamInVideo (options: OverrideCommandOptions & {
videoId: number | string
fixtureName?: string
return testFfmpegStreamError(command, options.shouldHaveError)
}
+ // ---------------------------------------------------------------------------
+
waitUntilPublished (options: OverrideCommandOptions & {
videoId: number | string
}) {
return this.waitUntilState({ videoId, state: VideoState.LIVE_ENDED })
}
- waitUntilSegmentGeneration (options: OverrideCommandOptions & {
+ async waitUntilSegmentGeneration (options: OverrideCommandOptions & {
+ server: PeerTubeServer
videoUUID: string
playlistNumber: number
segment: number
- totalSessions?: number
+ objectStorage: boolean
+ objectStorageBaseUrl?: string
}) {
- const { playlistNumber, segment, videoUUID, totalSessions = 1 } = options
+ const {
+ server,
+ objectStorage,
+ playlistNumber,
+ segment,
+ videoUUID,
+ objectStorageBaseUrl = ObjectStorageCommand.getMockPlaylistBaseUrl()
+ } = options
+
const segmentName = `${playlistNumber}-00000${segment}.ts`
+ const baseUrl = objectStorage
+ ? join(objectStorageBaseUrl, 'hls')
+ : server.url + '/static/streaming-playlists/hls'
+
+ let error = true
+
+ while (error) {
+ try {
+ // Check fragment exists
+ await this.getRawRequest({
+ ...options,
+
+ url: `${baseUrl}/${videoUUID}/${segmentName}`,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
+
+ const video = await server.videos.get({ id: videoUUID })
+ const hlsPlaylist = video.streamingPlaylists[0]
+
+ // Check SHA generation
+ const shaBody = await server.streamingPlaylists.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url, withRetry: objectStorage })
+ if (!shaBody[segmentName]) {
+ throw new Error('Segment SHA does not exist')
+ }
+
+ // Check fragment is in m3u8 playlist
+ const subPlaylist = await server.streamingPlaylists.get({ url: `${baseUrl}/${video.uuid}/${playlistNumber}.m3u8` })
+ if (!subPlaylist.includes(segmentName)) throw new Error('Fragment does not exist in playlist')
+
+ error = false
+ } catch {
+ error = true
+ await wait(100)
+ }
+ }
+ }
+
+ async waitUntilReplacedByReplay (options: OverrideCommandOptions & {
+ videoId: number | string
+ }) {
+ let video: VideoDetails
+
+ do {
+ video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId })
- return this.server.servers.waitUntilLog(`${videoUUID}/${segmentName}`, totalSessions * 2, false)
+ await wait(500)
+ } while (video.isLive === true || video.state.id !== VideoState.PUBLISHED)
}
- getSegment (options: OverrideCommandOptions & {
+ // ---------------------------------------------------------------------------
+
+ getSegmentFile (options: OverrideCommandOptions & {
videoUUID: string
playlistNumber: number
segment: number
+ objectStorage?: boolean // default false
}) {
- const { playlistNumber, segment, videoUUID } = options
+ const { playlistNumber, segment, videoUUID, objectStorage = false } = options
const segmentName = `${playlistNumber}-00000${segment}.ts`
- const url = `${this.server.url}/static/streaming-playlists/hls/${videoUUID}/${segmentName}`
+ const baseUrl = objectStorage
+ ? ObjectStorageCommand.getMockPlaylistBaseUrl()
+ : `${this.server.url}/static/streaming-playlists/hls`
+
+ const url = `${baseUrl}/${videoUUID}/${segmentName}`
return this.getRawRequest({
...options,
})
}
- async waitUntilReplacedByReplay (options: OverrideCommandOptions & {
- videoId: number | string
+ getPlaylistFile (options: OverrideCommandOptions & {
+ videoUUID: string
+ playlistName: string
+ objectStorage?: boolean // default false
}) {
- let video: VideoDetails
+ const { playlistName, videoUUID, objectStorage = false } = options
- do {
- video = await this.server.videos.getWithToken({ token: options.token, id: options.videoId })
+ const baseUrl = objectStorage
+ ? ObjectStorageCommand.getMockPlaylistBaseUrl()
+ : `${this.server.url}/static/streaming-playlists/hls`
- await wait(500)
- } while (video.isLive === true || video.state.id !== VideoState.PUBLISHED)
+ const url = `${baseUrl}/${videoUUID}/${playlistName}`
+
+ return this.getRawRequest({
+ ...options,
+
+ url,
+ implicitToken: false,
+ defaultExpectedStatus: HttpStatusCode.OK_200
+ })
}
+ // ---------------------------------------------------------------------------
+
async countPlaylists (options: OverrideCommandOptions & {
videoUUID: string
}) {