ニジカ投稿局 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.

video-source.ts 3.5 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import { type FileStorageType, type VideoSource } from '@peertube/peertube-models'
  2. import { STATIC_DOWNLOAD_PATHS, WEBSERVER } from '@server/initializers/constants.js'
  3. import { MVideoSource } from '@server/types/models/video/video-source.js'
  4. import { join } from 'path'
  5. import { Transaction } from 'sequelize'
  6. import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Table, UpdatedAt } from 'sequelize-typescript'
  7. import { SequelizeModel, doesExist, getSort } from '../shared/index.js'
  8. import { getResolutionLabel } from './formatter/video-api-format.js'
  9. import { VideoModel } from './video.js'
  10. @Table({
  11. tableName: 'videoSource',
  12. indexes: [
  13. {
  14. fields: [ 'videoId' ]
  15. },
  16. {
  17. fields: [ { name: 'createdAt', order: 'DESC' } ]
  18. },
  19. {
  20. fields: [ 'keptOriginalFilename' ],
  21. unique: true
  22. }
  23. ]
  24. })
  25. export class VideoSourceModel extends SequelizeModel<VideoSourceModel> {
  26. @CreatedAt
  27. createdAt: Date
  28. @UpdatedAt
  29. updatedAt: Date
  30. @AllowNull(false)
  31. @Column
  32. inputFilename: string
  33. @AllowNull(true)
  34. @Column
  35. keptOriginalFilename: string
  36. @AllowNull(true)
  37. @Column
  38. resolution: number
  39. @AllowNull(true)
  40. @Column
  41. width: number
  42. @AllowNull(true)
  43. @Column
  44. height: number
  45. @AllowNull(true)
  46. @Column
  47. fps: number
  48. @AllowNull(true)
  49. @Column(DataType.BIGINT)
  50. size: number
  51. @AllowNull(true)
  52. @Column(DataType.JSONB)
  53. metadata: any
  54. @AllowNull(true)
  55. @Column
  56. storage: FileStorageType
  57. @AllowNull(true)
  58. @Column
  59. fileUrl: string
  60. @ForeignKey(() => VideoModel)
  61. @Column
  62. videoId: number
  63. @BelongsTo(() => VideoModel, {
  64. foreignKey: {
  65. allowNull: false
  66. },
  67. onDelete: 'cascade'
  68. })
  69. Video: Awaited<VideoModel>
  70. static loadLatest (videoId: number, transaction?: Transaction) {
  71. return VideoSourceModel.findOne<MVideoSource>({
  72. where: { videoId },
  73. order: getSort('-createdAt'),
  74. transaction
  75. })
  76. }
  77. static loadByKeptOriginalFilename (keptOriginalFilename: string) {
  78. return VideoSourceModel.findOne<MVideoSource>({
  79. where: { keptOriginalFilename }
  80. })
  81. }
  82. static listAll (videoId: number, transaction?: Transaction) {
  83. return VideoSourceModel.findAll<MVideoSource>({
  84. where: { videoId },
  85. transaction
  86. })
  87. }
  88. // ---------------------------------------------------------------------------
  89. static async doesOwnedFileExist (filename: string, storage: FileStorageType) {
  90. const query = 'SELECT 1 FROM "videoSource" ' +
  91. 'INNER JOIN "video" ON "video"."id" = "videoSource"."videoId" AND "video"."remote" IS FALSE ' +
  92. `WHERE "keptOriginalFilename" = $filename AND "storage" = $storage LIMIT 1`
  93. return doesExist({ sequelize: this.sequelize, query, bind: { filename, storage } })
  94. }
  95. // ---------------------------------------------------------------------------
  96. getFileDownloadUrl () {
  97. if (!this.keptOriginalFilename) return null
  98. return WEBSERVER.URL + join(STATIC_DOWNLOAD_PATHS.ORIGINAL_VIDEO_FILE, this.keptOriginalFilename)
  99. }
  100. toFormattedJSON (): VideoSource {
  101. return {
  102. filename: this.inputFilename,
  103. inputFilename: this.inputFilename,
  104. fileUrl: this.fileUrl,
  105. fileDownloadUrl: this.getFileDownloadUrl(),
  106. resolution: {
  107. id: this.resolution,
  108. label: this.resolution !== null
  109. ? getResolutionLabel(this.resolution)
  110. : null
  111. },
  112. size: this.size,
  113. width: this.width,
  114. height: this.height,
  115. fps: this.fps,
  116. metadata: this.metadata,
  117. createdAt: this.createdAt.toISOString()
  118. }
  119. }
  120. }