• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

fluent-ffmpeg / node-fluent-ffmpeg / 6870338745

14 Nov 2023 10:34PM UTC coverage: 87.695% (-3.1%) from 90.801%
6870338745

Pull #1235

github

web-flow
Merge 29d32a66b into 4e02d1257
Pull Request #1235: V3 experiments

179 of 193 branches covered (0.0%)

898 of 1024 new or added lines in 13 files covered. (87.7%)

898 of 1024 relevant lines covered (87.7%)

5.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.47
/src/process.ts
1
import { spawn } from 'child_process'
1!
2

1✔
3
import { isWindows } from './utils/platform'
1✔
4
import {
1✔
5
  extractErrorMessage,
1✔
6
  extractProgress,
1✔
7
  ProgressInfo,
1✔
8
  CodecData,
1✔
9
  CodecDataExtractor
1✔
10
} from './utils/parsing'
1✔
11
import LineBuffer from './utils/line-buffer'
1✔
12

1✔
13
export interface RunResult {
1✔
14
  stderr: string
1✔
15
  stdout: string
1✔
16
}
1✔
17

1✔
18
export interface RunOptions {
1✔
19
  nice?: number
1✔
20
  cwd?: string
1✔
21
  onProgress?: (progress: ProgressInfo) => void
1✔
22
  onCodecData?: (data: CodecData) => void
1✔
23
  onStderr?: (line: string) => void
1✔
24
}
1✔
25

1✔
26
export interface ProcessOptions extends RunOptions {
1✔
27
  args: string[]
1✔
28
  captureStdout?: boolean
1✔
29
}
1✔
30

1✔
31
export class FfmpegProcess implements ProcessOptions {
10✔
32
  args: string[]
10✔
33
  nice?: number
10✔
34
  cwd?: string
10✔
35
  captureStdout?: boolean
10✔
36
  onProgress?: (progress: ProgressInfo) => void
10✔
37
  onCodecData?: (data: CodecData) => void
10✔
38
  onStderr?: (line: string) => void
10✔
39

10✔
40
  constructor(options: ProcessOptions) {
10✔
41
    this.args = options.args
10✔
42
    this.nice = options.nice
10✔
43
    this.cwd = options.cwd
10✔
44
    this.captureStdout = options.captureStdout
10✔
45
    this.onProgress = options.onProgress
10✔
46
    this.onCodecData = options.onCodecData
10✔
47
    this.onStderr = options.onStderr
10✔
48
  }
10✔
49

10✔
50
  run(callback?: (err: any, result?: any) => any): Promise<RunResult> {
10✔
51
    let cmd = process.env.FFMPEG_PATH || 'ffmpeg'
10✔
52
    let args: string[] = [...this.args]
10✔
53

10✔
54
    let { onProgress, onCodecData, onStderr } = this
10✔
55

10✔
56
    if (this.nice && this.nice !== 0 && !isWindows) {
10✔
57
      args = ['-n', this.nice.toString(), cmd, ...args]
1✔
58
      cmd = 'nice'
1✔
59
    }
1✔
60

10✔
61
    let promise: Promise<RunResult> = new Promise((resolve, reject) => {
10✔
62
      let child = spawn(cmd, args, {
10✔
63
        cwd: this.cwd,
10✔
64
        windowsHide: true
10✔
65
      })
10✔
66

10✔
67
      let stderr = new LineBuffer()
10✔
68
      let stdout = new LineBuffer()
10✔
69

10✔
70
      if (onStderr) {
10!
NEW
71
        stderr.on('line', onStderr)
×
NEW
72
      }
×
73

10✔
74
      if (onProgress) {
10!
NEW
75
        stderr.on('line', (line: string) => {
×
NEW
76
          let progress = extractProgress(line)
×
NEW
77
          if (progress) {
×
NEW
78
            onProgress?.(progress)
×
NEW
79
          }
×
NEW
80
        })
×
NEW
81
      }
×
82

10✔
83
      if (onCodecData) {
10!
NEW
84
        let extractor = new CodecDataExtractor(onCodecData)
×
NEW
85
        stderr.on('line', (line: string) => {
×
NEW
86
          if (!extractor.done) {
×
NEW
87
            extractor.processLine(line)
×
NEW
88
          }
×
NEW
89
        })
×
NEW
90
      }
×
91

10✔
92
      child.on('error', (err) => reject(err))
10✔
93

10✔
94
      child.on('close', (code, signal) => {
10✔
95
        stderr.close()
8✔
96
        stdout.close()
8✔
97

8✔
98
        if (signal) {
8✔
99
          reject(new Error(`ffmpeg was killed with signal ${signal}`))
1✔
100
        } else if (code) {
8✔
101
          let message = `ffmpeg exited with code ${code}`
2✔
102
          let error = extractErrorMessage(stderr.lines)
2✔
103

2✔
104
          if (error) {
2✔
105
            message = `${message}:\n${error}`
1✔
106
          }
1✔
107

2✔
108
          reject(new Error(message))
2✔
109
        } else {
7✔
110
          resolve({
5✔
111
            stdout: stdout.toString(),
5✔
112
            stderr: stderr.toString()
5✔
113
          })
5✔
114
        }
5✔
115
      })
10✔
116

10✔
117
      if (this.captureStdout) {
10!
NEW
118
        child.stdout.on('data', (data) => stdout.append(data.toString()))
×
NEW
119
      }
×
120

10✔
121
      child.stderr.on('data', (data) => stderr.append(data.toString()))
10✔
122
    })
10✔
123

10✔
124
    if (callback) {
10✔
125
      promise.then(
2✔
126
        (value) => callback(null, value),
2✔
127
        (reason) => callback(reason)
2✔
128
      )
2✔
129
    }
2✔
130

10✔
131
    return promise
10✔
132
  }
10✔
133
}
10✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc