31178


以下に示したコードは.mp4ファイルの秒数を一括取得するコマンドです。  
外部出力した場合は秒数のみ出力されます。

できれば外部出力せずそのまま出力を受取たいのですが、  
秒数以外の情報(ファイルのinput情報)も取得されてしまいます。  
外部出力と同じように秒数のみ取得するなら  
どのような処理になるのでしょうか？

[code]

        string コマンド="for /F %a in ('dir /b *.mp4') do (ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 %a >> mp4sec.txt)"
    
        System.Diagnostics.Process p = new System.Diagnostics.Process();
        p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec");
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardInput = false;
        p.StartInfo.CreateNoWindow = true
        p.StartInfo.Arguments = "/c " + コマンド ;
        p.Start();
    
        //出力を読み取る
        string results = p.StandardOutput.ReadToEnd();
    
[/code]

【環境】  
windows10 64bit  
visual stadio Express 2015 for desktop


CC BY-SA 3.0
2016-12-16T03:22:54.060
31174
2016-12-16T06:34:59.923
12778
question
c# ffmpeg command-line
C#のコマンドプロンプトで外部出力せずにinput情報を除いた結果を取得するには？


FORおよびDIRコマンドをC#で代替して1ファイルずつ`ffprobe.exe`を実行すればよいのでは。

[code]

    // var dirName = Environment.CurrentDirectory;
    foreach (var fileName in Directory.GetFiles(dirName, "*.mp4"))
    {
        string コマンド = "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 \"" + fileName + "\"";
    
        System.Diagnostics.Process p = new System.Diagnostics.Process();
        p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec");
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardInput = false;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.Arguments = "/c " + コマンド;
        p.Start();
        p.Start();
    
        //出力を読み取る
        string results = p.StandardOutput.ReadToEnd();
    }
    
[/code]


CC BY-SA 3.0
2016-12-16T04:02:06.987
31178
2016-12-16T04:02:06.987
5750
31174
answer


蛇足ですが、Explorerのプロパティにも時間情報があります。この情報でよければAPIで取得できます。

[code]

    static class PropertyStore {
        [StructLayout(LayoutKind.Sequential)]
        struct PROPERTYKEY {
            public Guid fmtid;
            public int pid;
    
            public static PROPERTYKEY FromName(string name) {
                PROPERTYKEY key;
                PSGetPropertyKeyFromName(name, out key);
                return key;
            }
        }
    
        [StructLayout(LayoutKind.Explicit)]
        struct PROPVARIANT {
            [FieldOffset(8)]
            public long hVal;
        }
    
        [ComImport, Guid("886d8eeb-8cf2-4446-8d02-cdba1dbdcf99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        interface IPropertyStore {
            void GetCount(out int cProps);
            void GetAt(int iProp, out PROPERTYKEY pkey);
            void GetValue([In] ref PROPERTYKEY key, out PROPVARIANT pv);
            void SetValue([In] ref PROPERTYKEY key, [In] ref PROPVARIANT propvar);
            void Commit();
        }
    
        [DllImport("Shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
        static extern void SHGetPropertyStoreFromParsingName(string pszPath, IntPtr pbc, int flags, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IPropertyStore ppv);
        [DllImport("Propsys.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
        static extern void PSGetPropertyKeyFromName(string pszString, out PROPERTYKEY pkey);
    
        static PROPERTYKEY durationKey = PROPERTYKEY.FromName("System.Media.Duration");
        public static TimeSpan GetDuration(string fullPath) {
            IPropertyStore ps;
            SHGetPropertyStoreFromParsingName(fullPath, IntPtr.Zero, 0, typeof(IPropertyStore).GUID, out ps);
            PROPVARIANT durationValue;
            ps.GetValue(ref durationKey, out durationValue);
            return TimeSpan.FromTicks(durationValue.hVal);
        }
    }
    
[/code]


CC BY-SA 3.0
2016-12-16T05:36:16.657
31179
2016-12-16T05:36:16.657
4236
31174
answer


> 秒数以外の情報(ファイルのinput情報)も取得されてしまいます。

何も考えずに for コマンドを使った場合、ループ内で実行されたコマンドが表示されます。これはC#を使わずコマンドプロンプトで for
コマンドを実行した場合も同じです。

[code]

    R:\>for /l %i in (1,1,3) do echo %i
    
    R:\>echo 1
    1
    
    R:\>echo 2
    2
    
    R:\>echo 3
    3
    
[/code]

実行したコマンドを表示せず、その実行結果だけを表示したい場合、

  * あらかじめ `ECHO OFF` コマンドを実行しておく
  * コマンドの頭に `@` を付ける

といった方法があります。バッチファイルでよく使われますね。

[code]

    R:\>for /l %i in (1,1,3) do @echo %i
    1
    2
    3
    
[/code]

今回のケースでもこれが使えます。

[code]

    string コマンド="for /F %a in ('dir /b *.mp4') do @(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 %a)"
    
[/code]


CC BY-SA 3.0
2016-12-16T06:21:16.083
31180
2016-12-16T06:34:59.923
2016-12-16T06:34:59.923
8000
8000
31174
answer