File size: 1,829 Bytes
f077067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import _ from 'lodash'
import fs from 'fs'
import { Plugin } from './plugin.js';
import { FFMpegUtils } from 'common-utils';

export class SpeedPlugin extends Plugin {
  constructor(name, options) {
    super(name, options);
  }

  async applyPrerender(originalManuscript, jobId) {

  }

  async applyPostrender(originalManuscript, jobId, outFiles) {
    for (let outFile of outFiles) {
      const speedFactor = this.options.speed || 1.0;
      if (speedFactor !== 1.0) {

        const tempFile = outFile + '.original.mp4';
        fs.renameSync(outFile, tempFile);
        try {
          const pts = 1.0 / speedFactor;
          if (pts <= 0) {
            return
          }

          // atempo only supports 0.5-2.0, so we chain filters to approximate the target
          let remaining = speedFactor;
          const atempoFilters = [];
          while (remaining > 2.0) {
            atempoFilters.push('atempo=2.0');
            remaining /= 2.0;
          }
          while (remaining < 0.5) {
            atempoFilters.push('atempo=0.5');
            remaining *= 2.0;
          }
          atempoFilters.push(`atempo=${remaining.toFixed(6)}`);
          const audioFilter = atempoFilters.join(',');
          this.log(`Speeding the video ${outFile} by a factor of x${speedFactor}`);
          const cmd = `ffmpeg -i ${tempFile} -filter_complex "[0:v]setpts=${pts.toFixed(6)}*PTS[v];[0:a]${audioFilter}[a]" -map "[v]" -map "[a]" ${outFile}`;
          await FFMpegUtils.execute(cmd);
          fs.unlinkSync(tempFile);
        } catch (err) {
          this.log(`Error applying speed change: ${err}`);
          if (fs.existsSync(outFile)) {
            fs.unlinkSync(outFile);
          }
          fs.renameSync(tempFile, outFile);
        }
      }
    }
  }
}