2013-04-10 20 views
8

Tôi đang cố gắng sử dụng ffmpeg (được biên dịch trên Windows với Cygwin) trong chương trình C#, bằng cách sử dụng lớp Process để sinh ra một cá thể ffmpeg. Tuy nhiên, tôi đã nhấn một lỗi khá kỳ lạ mà không có ý nghĩa nhiều.ffmpeg chạy từ shell chạy đúng, nhưng không khi được gọi từ bên trong .NET

Khi tôi chạy ffmpeg trực tiếp từ một vỏ (có thể là bash Cygwin của, PowerShell, cmd), ffmpeg thể không đúng cách giải mã và các tập tin reencode mà không cần bất kỳ vấn đề:

PS C:\audio> ffmpeg -i .\sound1.wav -acodec libvorbis -f ogg abc.ogg 
ffmpeg version 1.2 Copyright (c) 2000-2013 the FFmpeg developers 
    built on Apr 8 2013 15:10:40 with gcc 4.5.3 (GCC) 
    configuration: --disable-encoder=vorbis --enable-libvorbis 
    libavutil  52. 18.100/52. 18.100 
    libavcodec  54. 92.100/54. 92.100 
    libavformat 54. 63.104/54. 63.104 
    libavdevice 54. 3.103/54. 3.103 
    libavfilter  3. 42.103/3. 42.103 
    libswscale  2. 2.100/2. 2.100 
    libswresample 0. 17.102/0. 17.102 
[wav @ 0x800538a0] max_analyze_duration 5000000 reached at 5015510 microseconds 
Guessed Channel Layout for Input Stream #0.0 : stereo 
Input #0, wav, from '.\sound1.wav': 
    Metadata: 
    encoder   : Lavf54.63.104 
    Duration: 00:00:05.76, bitrate: 1411 kb/s 
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0]/0x0001), 44100 Hz, stereo, s16, 1411 kb/s 
Output #0, ogg, to 'abc.ogg': 
    Metadata: 
    encoder   : Lavf54.63.104 
    Stream #0:0: Audio: vorbis, 44100 Hz, stereo, fltp 
Stream mapping: 
    Stream #0:0 -> #0:0 (pcm_s16le -> libvorbis) 
Press [q] to stop, [?] for help 
size=  55kB time=00:00:05.74 bitrate= 78.5kbits/s 
video:0kB audio:51kB subtitle:0 global headers:4kB muxing overhead 0.817473% 

Các tập tin đóng tốt, và tôi có thể mã hóa sang WAV hoặc bất kỳ định dạng nào khác mà tôi thích. Tuy nhiên, khi tôi gọi ffmpeg từ C# với đoạn mã sau:

string tempfile = Path.GetTempFileName(); 
FileStream tempfilestr = File.OpenWrite(tempfile); 
input.CopyTo(tempfilestr); 

ProcessStartInfo pstart = new ProcessStartInfo("ffmpeg", string.Format("-i \"{0}\" -v verbose -y -f wav -", tempfile)); 
pstart.CreateNoWindow = true; 
pstart.ErrorDialog = false; 
pstart.RedirectStandardOutput = true; 
pstart.RedirectStandardError = true; 
pstart.UseShellExecute = false; 


Process proc = new Process(); 
proc.StartInfo = pstart; 
proc.Start(); 
StreamReader stdout = proc.StandardOutput; 
StreamReader stderr = proc.StandardError; 

outtempfilestr = File.OpenRead(outtempfile); 
MemoryStream output = new MemoryStream(); 

stdout.BaseStream.CopyTo(output); 

try { 
    proc.Kill(); 
} 
catch(InvalidOperationException) { } 
catch(Win32Exception) { } 

File.Delete(tempfile); 

return output.ToArray(); 

này một cách ngẫu nhiên sản xuất sai sót trong kết quả:

ffmpeg version 1.2 Copyright (c) 2000-2013 the FFmpeg developers 
    built on Apr 8 2013 15:10:40 with gcc 4.5.3 (GCC) 
    configuration: --disable-encoder=vorbis --enable-libvorbis 
    libavutil  52. 18.100/52. 18.100 
    libavcodec  54. 92.100/54. 92.100 
    libavformat 54. 63.104/54. 63.104 
    libavdevice 54. 3.103/54. 3.103 
    libavfilter  3. 42.103/3. 42.103 
    libswscale  2. 2.100/2. 2.100 
    libswresample 0. 17.102/0. 17.102 
[wav @ 0x80053860] parser not found for codec pcm_s16le, packets or times may be invalid. 
    Last message repeated 1 times 
[wav @ 0x80053860] max_analyze_duration 5000000 reached at 5015510 microseconds 
Guessed Channel Layout for Input Stream #0.0 : stereo 
Input #0, wav, from 'C:\Users\Bevin\AppData\Local\Temp\tmp1CCE.tmp': 
    Duration: 00:00:05.20, bitrate: 1411 kb/s 
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0]/0x0001), 44100 Hz, stereo, s16, 1411 kb/s 
[graph 0 input from stream 0:0 @ 0x8011f320] tb:1/44100 samplefmt:s16 samplerate:44100 chlayout:0x3 
Output #0, wav, to 'pipe:': 
    Metadata: 
    ISFT   : Lavf54.63.104 
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0]/0x0001), 44100 Hz, stereo, s16, 1411 kb/s 
Stream mapping: 
    Stream #0:0 -> #0:0 (pcm_s16le -> pcm_s16le) 
Press [q] to stop, [?] for help 
Multiple frames in a packet from stream 0 
[pcm_s16le @ 0x8005c160] Invalid PCM packet, data has size 3 but at least a size of 4 was expected 
Error while decoding stream #0:0: Invalid data found when processing input 
No more output streams to write to, finishing. 
size=  896kB time=00:00:05.20 bitrate=1411.3kbits/s  
video:0kB audio:896kB subtitle:0 global headers:0kB muxing overhead 0.008719% 

Lưu ý rằng các lỗi này không phải lúc nào xảy ra. Đôi khi chúng xảy ra đối với một số tệp nhất định, đôi khi chúng không xảy ra. Tôi đã thử các kết hợp khác nhau của các chuyển hướng luồng và các tệp tạm thời, không có tệp nào trong số chúng hoạt động. Tôi cũng đã kiểm tra tính toàn vẹn của các tệp tạm thời và tất cả đều kiểm tra. Tôi thậm chí đã trích xuất các tập tin tạm thời trước khi nó đã bị xóa, và giải mã nó trong vỏ mà không có một xô.

Bất kỳ ý tưởng nào?

Chỉnh sửa: Tôi đã thử chạy ffmpeg từ tập lệnh trình bao chạy qua C#. Nó cho cùng một vấn đề. Biên dịch ffmpeg qua MinGW cũng đưa ra cùng một vấn đề.

+0

bạn đã thử đặt đúng * thư mục hoạt động * chưa? Khi bạn chạy một ứng dụng từ trình bao, đường dẫn shell (chủ yếu là thư mục ứng dụng) được sử dụng làm thư mục làm việc, khi bạn chạy nó từ .net thư mục làm việc được chỉ định là thư mục của ứng dụng .net của bạn –

+0

@Gam Erix - Đường dẫn tệp được chuyển đến ffmpeg là tuyệt đối, vì vậy tôi không nghĩ rằng có bất kỳ vấn đề nào về kết thúc đó. – Bevin

+0

@ Bevin Bạn đã thử biên dịch ffmpeg bằng các thư viện liên kết tĩnh như thế nào? Có lẽ điều đó sẽ giúp giải quyết vấn đề này. Ngoài ra, ffmpeg có thể tìm kiếm codec (hoặc 'libavcodec') trong thư mục làm việc. Bạn có thể thử thiết lập thư mục làm việc ([Environment.CurrentDirectory'] (http://msdn.microsoft.com/en-us/library/system.environment.currentdirectory.aspx)) ngay trước 'proc.Start() 'gọi? – Jesse

Trả lời

8

Đó là vì cách bạn chuyển đối số. Thực hiện việc này:

Process process = new Process(); 
process.StartInfo.RedirectStandardOutput = true; 
process.StartInfo.RedirectStandardError = true; 
process.StartInfo.FileName = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + 
         @"\bin\ffmpeg.exe"; 

process.StartInfo.Arguments = "-i .\sound1.wav -acodec libvorbis -f ogg abc.ogg"; 


process.StartInfo.UseShellExecute = false; 
process.StartInfo.CreateNoWindow = true; 
process.Start(); 

Công trình này hoàn hảo.

+0

Tôi đồng ý với Omid và nếu bạn muốn làm việc, bạn phải sử dụng ký tự thoát cho tất cả các ký tự đặc biệt. – MarmiK

+0

Không cần chuỗi ký tự cần thiết hoặc thoát dấu gạch chéo ngược khi gán đối số, tức là '. \ Sound1 .wav' sẽ lỗi. –