ニジカ投稿局 https://tv.nizika.tv
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

live-utils.ts 3.2 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { pathExists, remove } from 'fs-extra/esm'
  2. import { readdir } from 'fs/promises'
  3. import { basename, join } from 'path'
  4. import { LiveVideoLatencyMode, LiveVideoLatencyModeType, FileStorage } from '@peertube/peertube-models'
  5. import { logger } from '@server/helpers/logger.js'
  6. import { VIDEO_LIVE } from '@server/initializers/constants.js'
  7. import { MStreamingPlaylist, MStreamingPlaylistVideo, MVideo } from '@server/types/models/index.js'
  8. import { listHLSFileKeysOf, removeHLSFileObjectStorageByFullKey, removeHLSObjectStorage } from '../object-storage/index.js'
  9. import { getLiveDirectory } from '../paths.js'
  10. function buildConcatenatedName (segmentOrPlaylistPath: string) {
  11. const num = basename(segmentOrPlaylistPath).match(/^(\d+)(-|\.)/)
  12. return 'concat-' + num[1] + '.ts'
  13. }
  14. async function cleanupAndDestroyPermanentLive (video: MVideo, streamingPlaylist: MStreamingPlaylist) {
  15. await cleanupTMPLiveFiles(video, streamingPlaylist)
  16. await streamingPlaylist.destroy()
  17. }
  18. async function cleanupUnsavedNormalLive (video: MVideo, streamingPlaylist: MStreamingPlaylist) {
  19. const hlsDirectory = getLiveDirectory(video)
  20. // We uploaded files to object storage too, remove them
  21. if (streamingPlaylist.storage === FileStorage.OBJECT_STORAGE) {
  22. await removeHLSObjectStorage(streamingPlaylist.withVideo(video))
  23. }
  24. await remove(hlsDirectory)
  25. await streamingPlaylist.destroy()
  26. }
  27. async function cleanupTMPLiveFiles (video: MVideo, streamingPlaylist: MStreamingPlaylist) {
  28. await cleanupTMPLiveFilesFromObjectStorage(streamingPlaylist.withVideo(video))
  29. await cleanupTMPLiveFilesFromFilesystem(video)
  30. }
  31. function getLiveSegmentTime (latencyMode: LiveVideoLatencyModeType) {
  32. if (latencyMode === LiveVideoLatencyMode.SMALL_LATENCY) {
  33. return VIDEO_LIVE.SEGMENT_TIME_SECONDS.SMALL_LATENCY
  34. }
  35. return VIDEO_LIVE.SEGMENT_TIME_SECONDS.DEFAULT_LATENCY
  36. }
  37. export {
  38. cleanupAndDestroyPermanentLive,
  39. cleanupUnsavedNormalLive,
  40. cleanupTMPLiveFiles,
  41. getLiveSegmentTime,
  42. buildConcatenatedName
  43. }
  44. // ---------------------------------------------------------------------------
  45. function isTMPLiveFile (name: string) {
  46. return name.endsWith('.ts') ||
  47. name.endsWith('.m3u8') ||
  48. name.endsWith('.json') ||
  49. name.endsWith('.mpd') ||
  50. name.endsWith('.m4s') ||
  51. name.endsWith('.tmp')
  52. }
  53. async function cleanupTMPLiveFilesFromFilesystem (video: MVideo) {
  54. const hlsDirectory = getLiveDirectory(video)
  55. if (!await pathExists(hlsDirectory)) return
  56. logger.info('Cleanup TMP live files from filesystem of %s.', hlsDirectory)
  57. const files = await readdir(hlsDirectory)
  58. for (const filename of files) {
  59. if (isTMPLiveFile(filename)) {
  60. const p = join(hlsDirectory, filename)
  61. remove(p)
  62. .catch(err => logger.error('Cannot remove %s.', p, { err }))
  63. }
  64. }
  65. }
  66. async function cleanupTMPLiveFilesFromObjectStorage (streamingPlaylist: MStreamingPlaylistVideo) {
  67. if (streamingPlaylist.storage !== FileStorage.OBJECT_STORAGE) return
  68. logger.info('Cleanup TMP live files from object storage for %s.', streamingPlaylist.Video.uuid)
  69. const keys = await listHLSFileKeysOf(streamingPlaylist)
  70. for (const key of keys) {
  71. if (isTMPLiveFile(key)) {
  72. await removeHLSFileObjectStorageByFullKey(key)
  73. }
  74. }
  75. }