我们需要在delphi应用程序的命令窗口中执行ffmpeg。
我们找到了使用“ExtractShortPathName”函数保护路径的解决方案。
但是在某些计算机上我们无法获得8.3路径(HKLM \ SYSTEM \ CurrentControlSet \ Control \ FileSystem \ NtfsDisable8dot3NameCreation为2),我们希望找到另一种逃避空间的方法。
以下是代码:
sParameters := '"C:\Users\[...]\input.wav" -r 12.03 -f image2 -i "C:\Users\[...]\delphilm%d.png" -vf "scale=1024:704" -ab 96k -r 24 -b 2000k -pass 1 -vcodec libx264 -fpre "C:\[...]\libx264-normal.ffpreset" "C:\Users\[...]\export.mp4"';
sCommand := 'C:\Program Files\My application\utils\bin\ffmpeg.exe';
Handle := CreateProcess(nil, PChar('cmd.exe /C '+ProtectPath(sCommand)+' '+sParameters),nil, nil, True, 0, nil, nil, SI, PI);
使用ProtectPath功能:
function ProtectPath(sCommand:Widestring):Widestring;
begin
Result := sCommand;
// get the 8.3 path
Result := ExtractShortPathName(sCommand);
// if 8.3 path is not accessible
if(Pos(' ', Result)>0)then begin
//Result := '"'+sCommand+'"'; --> do not work
//Result := StrReplace(sCommand, ' ','" "'); --> do not work
//Result := StrReplace(sCommand, ' ','^ '); --> do not work
//Result := StrReplace(sCommand, ' ','\ '); --> do not work
//Result := StrReplace(sCommand, ' ','\\ '); --> do not work
//Result := StrReplace(sCommand, ' ','/ '); --> do not work
//Result := StrReplace(sCommand, ' ','// '); --> do not work
end;
end;
有什么想法吗?
答案 0 :(得分:8)
您无需检索8.3文件名。如果它包含任何空格字符(就像你已经使用了一些FFMPEG参数一样),你所要做的就是用一对引号包装一个长路径。然后,完全摆脱cmd.exe
并直接调用ffmpeg.exe
。
sCommand := '"C:\Program Files\My application\utils\bin\ffmpeg.exe"';
sParameters := '"C:\Users\[...]\input.wav" -r 12.03 -f image2 -i "C:\Users\[...]\delphilm%d.png" -vf "scale=1024:704" -ab 96k -r 24 -b 2000k -pass 1 -vcodec libx264 -fpre "C:\[...]\libx264-normal.ffpreset" "C:\Users\[...]\export.mp4"';
Handle := CreateProcess(nil, PChar(sCommand + ' ' + sParameters), nil, nil, True, 0, nil, nil, SI, PI);
如果您想动态引用,请使用(Ansi)QuotedStr()
,例如:
function ProtectParam(sParam: String): String;
begin
if LastDelimiter(' "', sParam) <> 0 then
Result := QuotedStr(sParam)
else
Result := sParam;
end;
FFMPEG := 'C:\Program Files\My application\utils\bin\ffmpeg.exe';
InputFile := 'C:\Users\[...]\input.wav';
PngFile := 'C:\Users\[...]\delphilm%d.png';
PresetFile := 'C:\[...]\libx264-normal.ffpreset';
ExportFile := 'C:\Users\[...]\export.mp4';
sCommand := ProtectParam(FFMPEG) + ' ' + ProtectParam(InputFile) + ' -r 12.03 -f image2 -i ' + ProtectParam(PngFile) + ' -vf "scale=1024:704" -ab 96k -r 24 -b 2000k -pass 1 -vcodec libx264 -fpre ' + ProtectParam(PresetFile) + ' ' + ProtectParam(ExportFile);
Handle := CreateProcess(nil, PChar(sCommand), nil, nil, True, 0, nil, nil, SI, PI);
答案 1 :(得分:1)
我认为没有任何真正的理由在这里使用cmd.exe
。它只是增加了一层额外的复杂性来灼烧你。您要求cmd.exe
致电CreateProcess
以启动ffmpeg
,为什么不直接这样做?
尽管如此,一个廉价而愉快的解决问题的方法是利用工作目录。将'C:\Program Files\My application\utils\bin'
传递给新流程的工作目录,然后只需PChar('cmd.exe /C ffmpeg.exe '+sParameters)
。