@vpalmisano/webrtcperf 4.1.1 → 4.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/vmaf.ts CHANGED
@@ -75,7 +75,7 @@ export async function prepareVideo(
75
75
  await runShellCommand(
76
76
  `ffmpeg -hide_banner -loglevel warning -threads ${Math.min(cpus, 16)} \
77
77
  ${videoDuration ? `-t ${videoDuration}` : ''} \
78
- -i ${fpath} \
78
+ -stream_loop -1 -i ${fpath} \
79
79
  -filter_complex "[0:v]scale=w=${videoWidth || width}:h=${videoHeight || height},fps=${videoFramerate || frameRate},${filter}\
80
80
  drawbox=x=0:y=0:w=iw:h=${textHeight}:color=black:t=fill,\
81
81
  drawtext=fontfile=/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf:text='${id || 0}-%{eif\\:t*1000\\:u}':fontcolor=white:fontsize=${fontsize}:x=(w-text_w)/2:y=(${textHeight}-text_h)/2[out]" \
@@ -94,8 +94,9 @@ drawtext=fontfile=/usr/share/fonts/truetype/noto/NotoMono-Regular.ttf:text='${id
94
94
  * @param fpath The input video file path.
95
95
  * @param crop The crop filter.
96
96
  * @param keepSourceFile If the source file should be kept.
97
+ * @param skipDuplicated If the duplicated recognized frames should be skipped.
97
98
  */
98
- export async function convertToIvf(fpath: string, crop?: string, keepSourceFile = true) {
99
+ export async function convertToIvf(fpath: string, crop?: string, keepSourceFile = true, skipDuplicated = false) {
99
100
  const { width, height, frameRate } = await parseVideo(fpath)
100
101
  const outputPath = fpath.replace(/\.[^.]+$/, '.ivf.raw')
101
102
  log.debug(`convertToIvf ${fpath} ${width}x${height}@${frameRate} -> ${outputPath} crop:`, crop)
@@ -108,8 +109,11 @@ export async function convertToIvf(fpath: string, crop?: string, keepSourceFile
108
109
  -f ivf ${outputPath}`,
109
110
  true,
110
111
  )
112
+ if (!keepSourceFile) {
113
+ await fs.promises.unlink(fpath)
114
+ }
111
115
 
112
- await fixIvfFrames(outputPath, keepSourceFile)
116
+ await fixIvfFrames(outputPath, false, skipDuplicated)
113
117
  }
114
118
 
115
119
  /**
@@ -223,7 +227,7 @@ async function parseIvf(fpath: string, runRecognizer = false) {
223
227
  log.warn(`IVF file ${fname}: pts ${pts} <= prev ${ptsIndex[ptsIndex.length - 1]}`)
224
228
  } */
225
229
  if (frames.has(pts)) {
226
- /* log.debug(`IVF file ${fname}: pts ${pts} already present, skipping`) */
230
+ log.debug(`IVF file ${fname}: pts ${pts} already present, skipping`)
227
231
  skipped++
228
232
  } else {
229
233
  frames.set(pts, { pts, index, position, size: size + 12 })
@@ -262,8 +266,9 @@ ts: ${firstTimestamp.toFixed(2)}-${lastTimestamp.toFixed(2)} (${(lastTimestamp -
262
266
  }
263
267
  }
264
268
 
265
- export async function fixIvfFrames(filePath: string, keepSourceFile = true) {
269
+ export async function fixIvfFrames(filePath: string, keepSourceFile = true, skipDuplicated = false) {
266
270
  const fname = path.basename(filePath)
271
+ log.debug(`fixIvfFrames ${fname} keepSourceFile=${keepSourceFile} skipDuplicated=${skipDuplicated}`)
267
272
  const dirPath = path.dirname(filePath)
268
273
  if (!fname.endsWith('.ivf.raw')) {
269
274
  throw new Error(`fixIvfFrames ${fname}: invalid file extension, expected ".ivf.raw"`)
@@ -313,12 +318,16 @@ export async function fixIvfFrames(filePath: string, keepSourceFile = true) {
313
318
  if (nextFrame?.recognizedPts && (nextFrame?.recognizedPts || 0) < frame.recognizedPts) {
314
319
  continue
315
320
  }
316
- // Keep duplicated frames.
321
+ // Duplicated recognized frame.
317
322
  if (prevFrame?.recognizedPts && frame.recognizedPts === prevFrame.recognizedPts) {
318
- /* log.warn(
319
- `${frame.index} pts=${pts}:${frame.recognizedPts} prev ${prevFrame.pts}(${pts - prevFrame.pts}):${prevFrame.recognizedPts}(${frame.recognizedPts - prevFrame.recognizedPts}) next ${nextFrame?.pts}(${(nextFrame?.pts || 0) - pts}):${nextFrame?.recognizedPts}(${(nextFrame?.recognizedPts || 0) - frame.recognizedPts})`,
320
- ) */
321
- frame.recognizedPts = prevFrame.recognizedPts + 1
323
+ log.debug(
324
+ `${fname}: duplicate recognized frame pts=${pts}:${frame.recognizedPts} prev=${prevFrame.pts}:${prevFrame.recognizedPts} next=${nextFrame?.pts}:${nextFrame?.recognizedPts} (${skipDuplicated ? 'skipped' : 'fixed'})`,
325
+ )
326
+ if (skipDuplicated) {
327
+ continue
328
+ } else {
329
+ frame.recognizedPts += frame.pts - prevFrame.pts
330
+ }
322
331
  }
323
332
  const frameView = new DataView(new ArrayBuffer(frame.size))
324
333
  await fd.read(frameView, 0, frame.size, frame.position)
@@ -343,7 +352,8 @@ export async function fixIvfFrames(filePath: string, keepSourceFile = true) {
343
352
  return { participantDisplayName, outFilePath }
344
353
  }
345
354
 
346
- export async function fixIvfFiles(directory: string, keepSourceFiles = true) {
355
+ export async function fixIvfFiles(directory: string, keepSourceFiles = true, skipDuplicated = false) {
356
+ log.debug(`fixIvfFiles ${directory} keepSourceFiles=${keepSourceFiles} skipDuplicated=${skipDuplicated}`)
347
357
  const reference = new Map<string, string>()
348
358
  const degraded = new Map<string, string[]>()
349
359
 
@@ -381,7 +391,7 @@ export async function fixIvfFiles(directory: string, keepSourceFiles = true) {
381
391
  rawFiles,
382
392
  async filePath => {
383
393
  try {
384
- const { participantDisplayName, outFilePath } = await fixIvfFrames(filePath, keepSourceFiles)
394
+ const { participantDisplayName, outFilePath } = await fixIvfFrames(filePath, keepSourceFiles, skipDuplicated)
385
395
  return { participantDisplayName, outFilePath }
386
396
  } catch (err) {
387
397
  log.error(`fixIvfFrames error: ${(err as Error).stack}`)
@@ -690,16 +700,17 @@ interface VmafConfig {
690
700
  vmafKeepIntermediateFiles: boolean
691
701
  vmafKeepSourceFiles: boolean
692
702
  vmafCrop?: string
703
+ vmafSkipDuplicated?: boolean
693
704
  }
694
705
 
695
706
  export async function calculateVmafScore(config: VmafConfig): Promise<VmafScore[]> {
696
- const { vmafPath, vmafPreview, vmafKeepIntermediateFiles, vmafKeepSourceFiles, vmafCrop } = config
707
+ const { vmafPath, vmafPreview, vmafKeepIntermediateFiles, vmafKeepSourceFiles, vmafCrop, vmafSkipDuplicated } = config
697
708
  if (!fs.existsSync(config.vmafPath)) {
698
709
  throw new Error(`VMAF path ${config.vmafPath} does not exist`)
699
710
  }
700
711
  log.debug(`calculateVmafScore referencePath=${vmafPath}`)
701
712
 
702
- const { reference, degraded } = await fixIvfFiles(vmafPath, vmafKeepSourceFiles)
713
+ const { reference, degraded } = await fixIvfFiles(vmafPath, vmafKeepSourceFiles, vmafSkipDuplicated)
703
714
 
704
715
  const crop: VmafCrop | undefined = vmafCrop ? json5.parse(vmafCrop) : undefined
705
716