Skip to content

Commit

Permalink
fix: Quote file paths in calls to ffmpeg on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterC89 committed Feb 10, 2024
1 parent 08e36c7 commit 36e41a6
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 16 deletions.
8 changes: 8 additions & 0 deletions shared/packages/api/src/__tests__/filePath.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { escapeFilePath } from '../filePath'

describe('filePath', () => {
test('checkPath', () => {
expect(escapeFilePath('test/path')).toBe(process.platform === 'win32' ? '"test/path"' : 'test/path')
expect(escapeFilePath('C:\\test\\path')).toBe(process.platform === 'win32' ? '"C:\\test\\path"' : 'C:\\test\\path')
})
})
10 changes: 10 additions & 0 deletions shared/packages/api/src/filePath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Escape spaces in file path with double quotes on windows.
*
* @param {string} path File path to be escaped.
* @returns {string} Escaped file path.
* @see {@link https://ffmpeg.org/ffmpeg-utils.html#Quoting-and-escaping}
*/
export function escapeFilePath(path: string): string {
return process.platform === 'win32' ? `"${path}"` : path
}
1 change: 1 addition & 0 deletions shared/packages/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './adapterClient'
export * from './adapterServer'
export * from './appContainer'
export * from './config'
export * from './filePath'
export * from './expectationApi'
export * from './inputApi'
export * from './HelpfulEventEmitter'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
AccessorId,
promiseTimeout,
INNER_ACTION_TIMEOUT,
escapeFilePath,
} from '@sofie-package-manager/api'
import { LocalFolderAccessorHandle } from '../../../accessorHandlers/localFolder'
import { FileShareAccessorHandle } from '../../../accessorHandlers/fileShare'
Expand Down Expand Up @@ -451,9 +452,9 @@ export function proxyFFMpegArguments(
// Check target to see if we should tell ffmpeg which format to use:
let targetPath = ''
if (isLocalFolderAccessorHandle(targetHandle)) {
targetPath = targetHandle.fullPath
targetPath = escapeFilePath(targetHandle.fullPath)
} else if (isFileShareAccessorHandle(targetHandle)) {
targetPath = targetHandle.fullPath
targetPath = escapeFilePath(targetHandle.fullPath)
} else if (isHTTPProxyAccessorHandle(targetHandle)) {
targetPath = ''
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { FileShareAccessorHandle } from '../../../../accessorHandlers/fileShare'
import { HTTPProxyAccessorHandle } from '../../../../accessorHandlers/httpProxy'
import { LocalFolderAccessorHandle } from '../../../../accessorHandlers/localFolder'
import { assertNever, stringifyError } from '@sofie-package-manager/api'
import { assertNever, escapeFilePath, stringifyError } from '@sofie-package-manager/api'

export interface OverriddenFFMpegExecutables {
ffmpeg: string
Expand Down Expand Up @@ -104,11 +104,11 @@ export async function spawnFFMpeg<Metadata>(
let pipeStdOut = false
if (isLocalFolderAccessorHandle(targetHandle)) {
await mkdirp(path.dirname(targetHandle.fullPath)) // Create folder if it doesn't exist
args.push(targetHandle.fullPath)
args.push(escapeFilePath(targetHandle.fullPath))
} else if (isFileShareAccessorHandle(targetHandle)) {
await targetHandle.prepareFileAccess()
await mkdirp(path.dirname(targetHandle.fullPath)) // Create folder if it doesn't exist
args.push(targetHandle.fullPath)
args.push(escapeFilePath(targetHandle.fullPath))
} else if (isHTTPProxyAccessorHandle(targetHandle)) {
pipeStdOut = true
args.push('pipe:1') // pipe output to stdout
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { execFile, ChildProcess, spawn } from 'child_process'
import { Expectation, assertNever, Accessor, AccessorOnPackage, LoggerInstance } from '@sofie-package-manager/api'
import {
Expectation,
assertNever,
Accessor,
AccessorOnPackage,
LoggerInstance,
escapeFilePath,
} from '@sofie-package-manager/api'
import {
isQuantelClipAccessorHandle,
isLocalFolderAccessorHandle,
Expand Down Expand Up @@ -50,12 +57,12 @@ export function scanWithFFProbe(
let inputPath: string
let filePath: string
if (isLocalFolderAccessorHandle(sourceHandle)) {
inputPath = sourceHandle.fullPath
filePath = sourceHandle.filePath
inputPath = escapeFilePath(sourceHandle.fullPath)
filePath = escapeFilePath(sourceHandle.filePath)
} else if (isFileShareAccessorHandle(sourceHandle)) {
await sourceHandle.prepareFileAccess()
inputPath = sourceHandle.fullPath
filePath = sourceHandle.filePath
inputPath = escapeFilePath(sourceHandle.fullPath)
filePath = escapeFilePath(sourceHandle.filePath)
} else if (isHTTPAccessorHandle(sourceHandle)) {
inputPath = sourceHandle.fullUrl
filePath = sourceHandle.path
Expand Down Expand Up @@ -650,10 +657,10 @@ async function getFFMpegInputArgsFromAccessorHandle(
): Promise<string[]> {
const args: string[] = []
if (isLocalFolderAccessorHandle(sourceHandle)) {
args.push(`-i`, sourceHandle.fullPath)
args.push(`-i`, escapeFilePath(sourceHandle.fullPath))
} else if (isFileShareAccessorHandle(sourceHandle)) {
await sourceHandle.prepareFileAccess()
args.push(`-i`, sourceHandle.fullPath)
args.push(`-i`, escapeFilePath(sourceHandle.fullPath))
} else if (isHTTPAccessorHandle(sourceHandle)) {
args.push(`-i`, sourceHandle.fullUrl)
} else if (isHTTPProxyAccessorHandle(sourceHandle)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
assertNever,
stringifyError,
startTimer,
escapeFilePath,
} from '@sofie-package-manager/api'
import {
isFileShareAccessorHandle,
Expand Down Expand Up @@ -220,10 +221,10 @@ export const MediaFilePreview: ExpectationWindowsHandler = {

let inputPath: string
if (isLocalFolderAccessorHandle(sourceHandle)) {
inputPath = sourceHandle.fullPath
inputPath = escapeFilePath(sourceHandle.fullPath)
} else if (isFileShareAccessorHandle(sourceHandle)) {
await sourceHandle.prepareFileAccess()
inputPath = sourceHandle.fullPath
inputPath = escapeFilePath(sourceHandle.fullPath)
} else if (isHTTPAccessorHandle(sourceHandle)) {
inputPath = sourceHandle.fullUrl
} else if (isHTTPProxyAccessorHandle(sourceHandle)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
assertNever,
stringifyError,
startTimer,
escapeFilePath,
} from '@sofie-package-manager/api'
import { getStandardCost } from '../lib/lib'
import { GenericWorker } from '../../../worker'
Expand Down Expand Up @@ -220,10 +221,10 @@ export const MediaFileThumbnail: ExpectationWindowsHandler = {

let inputPath: string
if (isLocalFolderAccessorHandle(sourceHandle)) {
inputPath = sourceHandle.fullPath
inputPath = escapeFilePath(sourceHandle.fullPath)
} else if (isFileShareAccessorHandle(sourceHandle)) {
await sourceHandle.prepareFileAccess()
inputPath = sourceHandle.fullPath
inputPath = escapeFilePath(sourceHandle.fullPath)
} else if (isHTTPAccessorHandle(sourceHandle)) {
inputPath = sourceHandle.fullUrl
} else if (isHTTPProxyAccessorHandle(sourceHandle)) {
Expand Down

0 comments on commit 36e41a6

Please sign in to comment.