Chia

Chia plotterについて。
HDDが20台あり、SSDが5台ある。HDDの空き容量ぴったりに、SSDをまんべんなく使いながら、Chiaのplottingをしたい。HDDは文字の割当が足りないので、適当なフォルダにマウントしたとする。
madmax plotterにコマンドラインで指定では、上記の条件は満たせないので、プログラム書いた。久しぶりに。C#

相変わらずの無駄が多いクソプログラムだ。需要あればbinary貼ります。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace plothelper
{
    class Program
    {
        static void Main(string[] args)
        {
            Program pm = new Program();
            pm.Run();
        }

        static ulong plotsize = 108836888948;

        static string MadMaxPath = "";
        static string OptionText = "";
        static List<string> ssds = new List<string>();
        static List<string> dirs = new List<string>();

        /// <summary>
        /// HDDごとのタスクカウント
        /// </summary>
        Dictionary<string, int> HDDRestTaskCount = new Dictionary<string, int>();

        public void Run()
        {


            try
            {
                using (StreamReader sr = new StreamReader("config.txt", Encoding.GetEncoding("shift-jis")))
                {
                    string line = "", mode = "";
                    while (!sr.EndOfStream)
                    {
                        line = sr.ReadLine().Trim('\t', ' ').ToLower();
                        line = Regex.Replace(line, "#.*", "");
                        if (line == "") continue;
                        if (line.StartsWith("["))
                        {
                            mode = Regex.Match(line, "\\[(.*?)\\]").Groups[1].Value;
                            continue;
                        }

                        switch (mode)
                        {
                            case "madmax":
                                MadMaxPath = line;
                                break;
                            case "option":
                                OptionText = line;
                                break;
                            case "plotssd":
                                if (!line.EndsWith("\\")) line += "\\";
                                ssds.Add(line);
                                break;
                            case "dirs":
                                if (!line.EndsWith("\\")) line += "\\";
                                dirs.Add(line);
                                break;
                            case "":
                                break;
                        }
                    }
                }


            }
            catch
            {

            }

            //            string dir = "c:\\chia\\";


            /// リアルタイムで更新される、タスクカウント
            Dictionary<string, int> dirsTask = new Dictionary<string, int>();

            /// SSDを使っているかどうか?
            Dictionary<string, int> ssdsTask = new Dictionary<string, int>();

            foreach (string s in dirs)
            {
                var freespace = GetFreeSpaceOfPathInBytes(s);
                int count = (int)(freespace / plotsize);
                if (count < 1) continue;
                HDDRestTaskCount[s] = count; /// ディレクトリごとのタスク数

                /// 現在やっているタスクのカウント 今は0
                dirsTask[s] = 0;
            }

            /// SSDタスクカウントをゼロにする。
            foreach(string s in ssds)
            {
                ssdsTask[s] = 0;
            }


            List<PlotProcess> procs = new List<PlotProcess>();

            int plotcreationcount = 0;
            int plotcreationtimesum = 0;




            while (HDDRestTaskCount.Values.Sum() > 0)
            {
                Thread.Sleep(500);

                /// プロセスが終わってないかチェック。
                foreach (var p in procs)
                {
                    if (p.IsRunning() == false)
                    {
                        dirsTask[p.destdir]--;
                        ssdsTask[p.plotdir]--;

                        /// 終わったタスクのかかった時間を表示する
                        int tim = p.SpentTime;
                        plotcreationcount++;
                        plotcreationtimesum += tim;
                        int average = plotcreationtimesum / plotcreationcount / 1000;

                        Console.WriteLine("EndTask: " + tim / 1000 / 60 + "min.   Average: " + average / 60 + "min. " + 24 * 60 * 60 / (average / ssds.Count) + "plots/day  Rest:" + HDDRestTaskCount.Values.Sum() + "plots " + HDDRestTaskCount.Values.Sum() * average / 60 / 60 / ssds.Count + "hours");
                    }
                }


                procs.RemoveAll(p => p.IsRunning() == false);

                /// プロセスが満タンなら終了.
                /// 
                if (procs.Count == ssds.Count) continue;

                /// タスクが少ないHDDを探したい
                string taskLowDir = (from d in dirsTask orderby d.Value ascending where HDDRestTaskCount[d.Key] > 0 select d.Key).FirstOrDefault();

                /// 使っていないSSDを探す
                string taskSSD = (from s in ssdsTask where s.Value == 0 select s.Key).FirstOrDefault();

                /// SSDが見つからなかったらループする。
                if (taskSSD == null) continue;

                Console.WriteLine(taskLowDir + " Rest:" + HDDRestTaskCount[taskLowDir] + " SSD: " + taskSSD );
                PlotProcess pp = new PlotProcess(taskLowDir, taskSSD);
                pp.Start();
                procs.Add(pp);
                ///タスクを始めたら++する。
                dirsTask[taskLowDir]++;
                ssdsTask[taskSSD]++;
                HDDRestTaskCount[taskLowDir]--;
            }


            //            Console.WriteLine(dir + "  " + freespace / 1024 / 1024 / 1024 + "Gib Free");
            Console.ReadLine();




        }

        static Random random = new Random();

        class PlotProcess
        {
            /// SSD1つにつき、plotタスクは1本ずつ走らせる
            /// SSD5枚あれば、常に5本のplotタスクは動いている
            /// 例えば、HDD1にE:\を使い、HDD2にF:\を使い、HDD3にG:\を使い・・・
            /// 終わり次第、余ったSSDは別のタスクへ。
            /// SSDをクラスにして、そのクラスでタスク管理したほうが良さそう。
            /// 今、動かしているSSDとHDDを記録しておく必要あり?
            /// タスクが終わり次第、余っているSSDとHDDを組み合わせていく?
            /// どれだけタスクが必要かどうか、一旦計算するとか・・・
            /// HDDにタスクをスタックしておく?
            /// 
            /// 1回やるタスク。
            public string destdir;
            public string plotdir;
            Process p = null;

            int starttime = 0;
            int debug_waittime = 0;

            public PlotProcess(string dest, string plot)
            {
                destdir = dest;
                plotdir = plot;

                debug_waittime = random.Next(1000, 10000);
            }

            public int SpentTime
            {
                get
                {
                    return Environment.TickCount - starttime;
                }
            }

            public void Start()
            {
                string cmdtext = "-n 1 -d " + destdir + " -t " + plotdir + " " + OptionText;
                // Console.WriteLine("start " + MadMaxPath + " " + cmdtext);

                // debug comment
                p = Process.Start(MadMaxPath, cmdtext);
                starttime = Environment.TickCount;
            }

            public bool IsRunning()
            {
                /// debug
                //if (Environment.TickCount - starttime > debug_waittime) return false; else return true;
                return !p.HasExited;
            }
        }

        public static ulong GetFreeSpaceOfPathInBytes(string path)
        {
            if ((new Uri(path)).IsUnc)
            {
                throw new NotImplementedException("Cannot find free space for UNC path " + path);
            }

            ulong freeSpace = 0;
            int prevVolumeNameLength = 0;

            foreach (ManagementObject volume in
                    new ManagementObjectSearcher("Select * from Win32_Volume").Get())
            {
                string name = volume["Name"].ToString();
                string pathh = path.ToLower();
                if (!pathh.EndsWith("\\")) pathh += "\\";
                if (UInt32.Parse(volume["DriveType"].ToString()) > 1 &&                             // Is Volume monuted on Host
                    volume["Name"] != null &&                                                       // Volume has a root directory
                    pathh == (volume["Name"].ToString()).ToLower()  // Required Path is under Volume's root directory 
                    )
                {
                    // If multiple volumes have their root directory matching the required path,
                    // one with most nested (longest) Volume Name is given preference.
                    // Case: CSV volumes monuted under other drive volumes.

                    int currVolumeNameLength = volume["Name"].ToString().Length;

                    if ((prevVolumeNameLength == 0 || currVolumeNameLength > prevVolumeNameLength) &&
                        volume["FreeSpace"] != null
                        )
                    {
                        freeSpace = ulong.Parse(volume["FreeSpace"].ToString());
                        prevVolumeNameLength = volume["Name"].ToString().Length;
                    }
                }
            }

            if (prevVolumeNameLength > 0)
            {
                return freeSpace;
            }

            //throw new Exception("Could not find Volume Information for path " + path);
            return 0;
        }

    }




}


設定ファイルに次の通り記載する。

[madmax] #plotterの場所
C:\Users\Hoge\Desktop\madmax\chia_plot

[option]
-r 4 -c xch10xpf~ec5kdql29cew -f 8d05a7~a1329bfcb1

[plotssd]
D:\
E:\
I:\
K:\
L:\

[dirs]
c:\chia\hdd01
c:\chia\hdd02
c:\chia\hdd03
c:\chia\hdd04
c:\chia\hdd05
c:\chia\hdd06
c:\chia\hdd07
c:\chia\hdd08
c:\chia\hdd09
c:\chia\hdd10
c:\chia\hdd11
c:\chia\hdd12
c:\chia\hdd13
c:\chia\hdd14
c:\chia\hdd15

同一フォルダにおいておく。あとは、dirsにあるHDDに対して、plotssdにあるものを取りながらplotしてくれる。
今の所、5SSD並列で動かして45plots / dayってところ。

興味の変遷

投稿7年ぶりになるっぽい

 

見るとこの7年間に色々あったなあ

独立 → 法人化 → 多事業展開 → 不動産業も開始

このところはプログラムへの熱が冷めて不動産ばっかり。

 

この前のAIで不動産探していた人じゃないけど、不動産の価格を調査するプログラム作ってみても楽しいのかもね?

 

不動産買いまくってすでに在庫1億超え 大丈夫か?

 

まあ、とりあえず本業と不動産と楽しんでやっていきましょうかね。

fft3dgpuの管理について

fft3dgpuは精度が良く、GPUさえ早ければSetMTModeでも使える便利なフィルタ。
しかし、僕の運用では問題が発生した。
それは、リモートデスクトップでログインした後に、自動でbatが開始されると、そのときにDirect3Dの初期化に失敗するということ。

なるほど、fft3dgpuの仕組みから行くとDirect3Dからhlslでピクセルシェーダーを起動してやっているっぽいが、
リモートデスクトップから接続が切れるとセッションが宙ぶらりんの状況になり、Direct3Dの初期化ができないみたいだ。
それがただ失敗するだけなら良いんだけど、なぜかaviutlのauc_waitが終了してしまい、次のエンコードタスクが再開され、どんどんaviutlのクラッシュが蓄積してメモリが圧迫され、最終的にspinelが落ちるという最悪の事態が発生、先週のアクセルワールドの録画に失敗して最悪だった。


そこで、query sessionを実行することによって、セッションが宙ぶらりんかどうか判定できるので、
「>」の後が空白のものがある時は、aviutlを実行しないようにした。

また、aviutlがクラッシュしている状態があるときには、aviutlを実行しないようにした。

これで、セッションが開かれていない時には、新たなエンコードタスクが始まらないようにすることで、「録画できていない」という最悪の事態だけは避けることができる。

できれば、リモートデスクトップから切断したら、ローカルのセッションで自動的にログオンしてくれればいいのになーと思うけれど、方法がわからない。
今現在は、crazyremoteとかvncからログインしておくようにしてるけれど。

AT-XのCMカットについて

AT-Xでは、本編の前に決まって「AT-X」の文字と、終了時に「離れて見て下さい」の文字が出現し、その前後は真っ黒な画面が数十フレーム入る。
そのため、その特性を活かしてCMカットを考えてみた。

SetMemoryMax(128)
SetMemoryMax(512)
LoadPlugin("O:\PT2\Encoder\avisynth\warpsharp.dll")
LoadAviUtlInputPlugin("O:\PT2\Encoder\aviutl\vfp\m2v.vfp", "MPEG2VIDEO")
vSrc = MPEG2VIDEO("T:\new\2012050813300001-[AT−X]ノワール #2.m2v")
vSrc=KillAudio(vSrc)
aSrc = WavSource("T:\new\2012050813300001-[AT−X]ノワール #2.wav")
aSrc=KillVideo(aSrc)
AudioDubEx(vSrc,aSrc)
global subtclip1 = ImageSource("O:\PT2\Encoder\avisynth\at-x_begin.bmp", end = FrameCount(), fps=29.97, use_DevIL=true)
global subtclip2 = ImageSource("O:\PT2\Encoder\avisynth\at-x_end.bmp", end = FrameCount(), fps=29.97, use_DevIL=true)

global filename1="T:\new\2012050813300001-[AT−X]ノワール #2_info.txt"
global kugiri = ":"

global clip1 = last.ConvertToYV12()
global subt1=overlay(subtclip1.crop(312, 228, 100, 52).ConvertToRGB24(), clip1.crop(312, 228, 100, 52).ConvertToRGB24(), mode="Difference").ConvertToYV12()
#global subt1=overlay(subtclip1.crop(16, 100, 52, 100).ConvertToRGB24(), clip1.crop(16, 100, 52, 100).ConvertToRGB24(), mode="Difference").ConvertToYV12()
global subt2=overlay(subtclip2.crop(456, 192, 100, 52).ConvertToRGB24(), clip1.crop(456, 192, 100, 52).ConvertToRGB24(), mode="Difference").ConvertToYV12()
WriteFileIf(subt1, filename1,"(luma<16.1)||(luma1<135)||(luma2<135)", "current_frame","kugiri", "luma", "kugiri", "luma1", "kugiri", "luma2")
FrameEvaluate("global luma1=AverageLuma(subt1)")
FrameEvaluate("global luma2=AverageLuma(subt2)")
FrameEvaluate("global luma=AverageLuma(clip1)")
ConvertToYUY2(interlaced=true)
return last

そのスクリプトがこれ。
まずはat-x_begin.bmpat-x_end.bmpを用意する。
beginの方は2012/5/08現在、周りに蝶が羽ばたいていてど真ん中にAT-Xの文字がある黄色いやつ。
それを完全に黒いフレームが始まる直前のフレームを、aviutlの連番BMPで1枚だけ出力したもの。
at-x_end.bmpは、本編終了後の「アニメを見るときは・・・」が書いてある部分の最後のフレーム。
最後のフレームを使う理由は、アニメはすべてが24分きっかりで終わるわけではなくて、そのズレた時間をこのテロップの部分で調整していると思われるため。
比較対象となる画像を読み込み、avisynthで処理しているフレームとの差異を取り、その明るさを保存する。
たとえば、初めのチョウチョの出ているところではluma1が128に近い値となり、本編終了後のテロップの部分ではluma2が128に近い値となる。
これらは全部の画面を比較する意味はあんまり無いので、cropして特に特徴のある部分にしてある。(subtclip1は、真ん中のAT-Xの文字のところ、subtclip2は、左下の文字がはっきりと読み取れるところ。)
これによりだいたい3〜4分もあれば解析が完了する。

この後、info.txtファイル内に

112:166.326370:132.143646:190.297302
113:167.122818:130.929993:185.451157
114:167.120514:130.845764:185.450958
115:167.985062:130.807693:189.659424
116:167.951904:130.790955:189.657501
117:169.090378:130.784225:189.237503
118:169.159134:130.759613:189.254608
119:169.983185:130.784805:189.557495
120:170.665176:132.089417:187.365005
121:170.714005:132.077698:187.367111
122:172.357834:131.361160:188.507889
123:172.401108:131.359802:188.502502
124:174.604614:131.199417:187.083267
125:174.661499:131.201340:187.092499
126:175.773041:130.895004:186.168076
127:175.798813:130.887314:186.166351
128:175.911865:130.700378:184.874619
129:175.931717:130.703262:184.884811
130:176.658157:130.693848:182.637878
131:176.687622:130.693848:182.632111
132:178.307678:130.636917:180.558853
133:178.338272:130.636917:180.557495
134:178.854950:130.610962:179.040390
135:179.108368:130.643646:178.890579
136:179.139786:130.647110:178.886917
137:181.022003:130.532700:177.662888
138:181.055679:130.533081:177.663269
139:183.154343:130.498657:176.791153
140:183.191010:130.496353:176.794617
141:183.566589:130.476532:178.825378
142:183.634476:130.379608:178.845963
143:183.520187:130.354614:178.505966
144:183.559967:130.389420:178.500198
145:184.156494:130.309998:177.984238
146:184.318832:130.294418:177.973083
147:185.314697:130.290771:177.507507
148:185.358978:130.289612:177.509995
149:185.208435:130.345764:177.105957
150:185.596161:130.333649:176.783661
151:185.633484:130.310776:176.784424
152:187.035172:130.264420:176.645187
153:187.055313:130.199615:176.632309
154:188.398407:130.129807:176.539612
155:188.430206:130.061157:176.538849
156:188.580109:130.063263:176.469040
157:188.645081:130.040573:176.477310
158:188.712326:130.040573:176.597504
159:188.737000:130.006729:176.581345
160:188.999725:130.004044:176.957886
161:189.081589:129.976730:176.996155
162:189.753693:130.050964:177.189621
163:189.806595:130.018082:177.211929
164:189.783340:130.019623:177.324615
165:190.424118:129.974808:177.644806
166:190.462814:129.927887:177.647110
167:191.937057:129.921539:177.855377
168:191.947144:129.915771:177.850006
169:192.685913:129.860001:177.983459
170:192.728424:129.809616:178.012878
171:193.089752:129.807495:177.798264
172:193.197937:129.786545:177.824615
173:193.456268:129.814041:177.524811
174:193.460663:129.809616:177.518646
175:194.018524:129.632889:177.193069
176:194.143829:129.632690:177.187698
177:194.035828:129.628464:176.923660
178:193.923309:129.618851:176.919418
179:193.655777:129.615967:176.895584
180:16.000191:228.565765:199.601730
181:16.000153:228.565765:199.601730
182:16.000162:228.565765:199.601730
183:16.000162:228.565765:199.601730
184:16.000162:228.565765:199.601730
185:16.000162:228.565765:199.601730
186:16.000162:228.565765:199.601730
187:16.000162:228.565765:199.601730
188:16.000162:228.565765:199.601730
189:16.000162:228.565765:199.601730
190:16.000162:228.565765:199.601730
191:16.000162:228.565765:199.601730
192:16.000162:228.565765:199.601730
193:16.000162:228.565765:199.601730
194:16.000162:228.565765:199.601730
195:16.000162:228.565765:199.601730
196:16.000162:228.565765:199.601730
197:16.000162:228.565765:199.601730
198:16.000162:228.565765:199.601730
199:16.000162:228.565765:199.601730
200:16.000162:228.565765:199.601730
201:16.000162:228.565765:199.601730
202:16.000162:228.565765:199.601730
203:16.000162:228.565765:199.601730
204:16.000162:228.565765:199.601730
205:16.000162:228.565765:199.601730
206:16.000162:228.565765:199.601730
207:16.000162:228.565765:199.601730
208:16.000162:228.565765:199.601730
209:16.000000:228.565765:199.601730
210:16.000000:228.565765:199.601730
211:16.000000:228.565765:199.601730
212:16.000000:228.565765:199.601730
213:16.000000:228.565765:199.601730
214:16.000000:228.565765:199.601730
215:16.000000:228.565765:199.601730
216:16.000000:228.565765:199.601730
217:16.000000:228.565765:199.601730
218:16.000000:228.565765:199.601730
219:16.000000:228.565765:199.601730
220:16.000000:228.565765:199.601730
221:16.000000:228.565765:199.601730
222:16.000000:228.565765:199.601730
223:16.000000:228.565765:199.601730
224:16.000000:228.565765:199.601730
225:16.000000:228.565765:199.601730
226:16.000000:228.565765:199.601730
227:16.000000:228.565765:199.601730
228:16.000000:228.565765:199.601730
229:16.000000:228.565765:199.601730
230:16.000000:228.565765:199.601730
231:16.000000:228.565765:199.601730
232:16.000000:228.565765:199.601730
233:16.000000:228.565765:199.601730
234:16.000000:228.565765:199.601730
235:16.000000:228.565765:199.601730
236:16.000000:228.565765:199.601730
237:16.000000:228.565765:199.601730
238:16.000000:228.565765:199.601730
239:16.000000:228.565765:199.601730
44056:16.000000:228.565765:199.601730
44057:16.000000:228.565765:199.601730
44058:16.000000:228.565765:199.601730
44059:16.000000:228.565765:199.601730
44060:16.000000:228.565765:199.601730
44061:16.000000:228.565765:199.601730
44062:16.000000:228.565765:199.601730
44063:16.000000:228.565765:199.601730
44064:16.000000:228.565765:199.601730
44065:16.000000:228.565765:199.601730
44066:16.000000:228.565765:199.601730
44067:16.000000:228.565765:199.601730
44068:16.000000:228.565765:199.601730
44069:16.000000:228.565765:199.601730
44070:16.000000:228.565765:199.601730
44071:16.000000:228.565765:199.601730
44072:16.000000:228.565765:199.601730
44073:16.000000:228.565765:199.601730
44074:16.000000:228.565765:199.601730
44075:16.000000:228.565765:199.601730
44076:16.000000:228.565765:199.601730
44077:16.000000:228.565765:199.601730
44078:16.000000:228.565765:199.601730
44079:16.000000:228.565765:199.601730
44080:16.000000:228.565765:199.601730
44081:16.000000:228.565765:199.601730
44082:16.000000:228.565765:199.601730
44083:16.000000:228.565765:199.601730
44084:16.000000:228.565765:199.601730
44085:16.000000:228.565765:199.601730
44986:190.343353:176.342117:128.554230
44987:190.350616:176.339996:128.550583
44988:190.386856:176.350388:128.573074
44989:190.422272:176.347305:128.576920
44990:190.462646:176.347687:128.572495
44991:190.507553:176.346161:128.598846
44992:190.558701:176.350967:128.605377
44993:190.622559:176.355957:128.600769
44994:190.703995:176.357315:128.605377
44995:190.783539:176.358078:128.610001
44996:190.857727:176.356735:128.615768
44997:190.933243:176.359802:128.624237
44998:191.011398:176.358841:128.627121
44999:191.102249:176.359802:128.630188
45000:191.192825:176.358841:128.634811
45001:191.263916:176.358459:128.635574
45002:191.308365:176.360199:128.642685
45003:191.344879:176.363266:128.642685
45004:191.379639:176.320190:128.643646
45005:191.406082:176.153076:128.646347
45006:191.433777:175.848083:128.652496
45007:191.464600:175.699417:128.656921
45008:191.498169:175.704224:128.650391
45009:191.532303:175.875763:128.647308
45010:191.558105:176.138458:128.644226
45011:191.569641:176.279800:128.645767
45012:191.574631:176.325378:128.648270
45013:191.568192:176.347122:128.644226
45014:191.557907:176.343658:128.646347
45015:191.535950:176.354996:128.645584
45016:191.504425:176.356155:128.644226
45017:191.466202:176.339996:128.570572
45018:191.454330:176.352890:128.589615
45019:191.438126:176.356735:128.586929
45020:191.412354:176.353271:128.588272
45021:191.378250:176.357697:128.606735
45022:191.335648:176.359039:128.627121
45023:191.279709:176.352493:128.605576
45024:191.219772:176.348267:128.631729
45025:191.158447:176.349228:128.637878
45026:191.092621:176.349426:128.627304
45027:191.036804:176.350189:128.638657
45028:190.973038:176.353851:128.643646
45029:190.907669:176.350967:128.638657
45030:190.875870:176.351151:128.643646
45031:190.868881:176.351151:128.648270
45032:190.880325:176.349426:128.648651
45033:190.906754:176.354813:128.651154
45034:190.926880:176.354813:128.663071
45035:190.942719:176.351532:128.657120
45036:190.973343:176.353851:128.651154
45037:191.023697:176.352890:128.664810
45038:191.087753:176.355774:128.654419
45039:191.158676:176.354614:128.657501
45040:191.217850:176.357117:128.659424
45041:191.268600:176.356155:128.662308
45042:191.339249:176.354813:128.661346
45043:191.428375:176.360962:128.674225
45044:191.518204:176.363266:128.667114
45045:191.595535:176.362885:128.667496
45046:191.644775:176.357880:128.666534
45047:191.680588:176.337692:128.558853
45048:191.724136:176.262878:128.576340
45049:191.761292:176.000000:128.569611
45050:191.795059:175.691345:128.571152
45051:191.830124:175.520767:128.590195
45052:191.860367:175.570770:128.591736
45053:191.873611:175.766541:128.583847
45054:191.883301:176.025772:128.584229
45055:191.880280:176.236160:128.593842
45056:191.857117:176.312698:128.585388
45057:191.833084:176.344620:128.588455
45058:191.794113:176.345764:128.598465
45059:191.745529:176.343460:128.594040
45060:191.690598:176.348083:128.608459
45061:191.623795:176.345963:128.606918
45062:191.561829:176.343460:128.606918
45063:191.509567:176.346725:128.608078
45064:191.452057:176.347122:128.612686
45065:191.375626:176.343262:128.622696
45066:191.282684:176.349808:128.636353
45067:191.172394:176.347687:128.627686
45068:191.044189:176.347885:128.624237
45069:190.903366:176.349045:128.632690
45070:190.786316:176.345581:128.631546
45071:190.698914:176.348083:128.637115
45072:190.626480:176.349609:128.637115
45073:190.548294:176.348846:128.644424
45074:190.479477:176.348267:128.641159
45075:190.430649:176.351730:128.622879
45076:190.409592:176.360382:128.624237
45077:190.408447:176.336151:128.573273
45078:190.426895:176.348083:128.589615
45079:190.440140:176.349045:128.582886
45080:190.457794:176.348648:128.578079
45081:190.487579:176.354416:128.602692
45082:190.532333:176.355194:128.608078
45083:190.599106:176.353851:128.596924
45084:190.674164:176.359238:128.603455
45085:190.740204:176.357117:128.608276
45086:190.812531:176.361725:128.605194
45087:190.902618:176.360199:128.613083
45088:191.001068:176.361160:128.615967
45089:191.092072:176.362503:128.615768
45090:191.162170:176.357498:128.613846
45091:191.194702:176.206146:128.621155
45092:191.211823:175.888275:128.619431
45093:191.234497:175.516159:128.630569
45094:191.241119:175.309814:128.630768
45095:191.246155:175.339996:128.630386
45096:191.253616:175.591537:128.641922
45097:191.255066:175.860382:128.640762
45098:191.239273:176.103073:128.635773
45099:191.225174:176.270386:128.639999
45100:191.194519:176.331345:128.642303
45101:191.154541:176.338074:128.640579
45102:191.118668:176.342697:128.639236
45103:191.069534:176.348083:128.639999
45104:191.011276:176.338455:128.638840
45105:190.951263:176.350189:128.640198
45106:190.885452:176.349045:128.637115
45107:190.824570:176.337112:128.569427
45108:190.777328:176.347122:128.569809
45109:190.698502:176.347687:128.568069
45110:190.583069:176.347885:128.568268
45111:190.456741:176.340775:128.599426
45112:190.325363:176.345200:128.610199
45113:190.216766:176.350571:128.592880
45114:190.137909:176.347122:128.612122
45115:190.074417:176.346924:128.616928
45116:190.022186:176.348083:128.618851
45117:189.984207:176.349426:128.622314
45118:189.949158:176.351532:128.620575
45119:189.923889:176.349045:128.626541
45120:189.917145:176.346924:128.628647
45121:189.919769:176.344421:128.632507
45122:189.933380:176.346924:128.634232
45123:189.958344:176.347305:128.637497
45124:189.984131:176.345383:128.638275
45125:190.017166:176.350769:128.642303
45126:190.062424:176.354614:128.644806
45127:190.115692:176.346344:128.656342
45128:190.185379:176.348465:128.650391
45129:190.267014:176.347504:128.646347
45130:190.342743:176.352692:128.657883
45131:190.421890:176.349045:128.658661
45132:190.501816:176.348648:128.655960
45133:190.572327:176.352112:128.655380
45134:190.612885:176.206146:128.656921
45135:190.624207:175.849609:128.655762
45136:190.622803:175.497116:128.655762
45137:190.623062:175.301544:128.572495
45138:190.629898:175.398651:128.598846
45139:190.628235:175.659805:128.598083
45140:190.636444:175.916733:128.590378
45141:190.652588:176.151535:128.612305
45142:190.658951:176.298843:128.622879
45143:190.648895:176.323853:128.612122
45144:190.641357:176.341537:128.617111
45145:190.620682:176.340958:128.620193
45146:190.583450:176.337112:128.615189
45147:190.540176:176.339996:128.630005
45148:190.498077:176.344238:128.638657
45149:190.454453:176.342880:128.636154
45150:190.421173:176.342499:128.638458
45151:190.375244:176.344238:128.643646
45152:190.311127:176.344238:128.643082
45153:190.234344:176.346161:128.638840
45154:190.132614:176.345764:128.651733
45155:190.019058:176.345001:128.647507
45156:189.931396:176.346344:128.649231
45157:189.866531:176.348083:128.656738
45158:189.810806:176.348083:128.654037
45159:189.771408:176.345963:128.657303
45160:189.754181:176.351151:128.654419
45161:189.748306:176.350006:128.654419
45162:189.761368:176.352112:128.652878
45163:189.788681:176.349609:128.656738
45164:189.815994:176.353653:128.651535
45165:189.852509:176.360962:128.653458
45166:189.897018:176.361343:128.652496
45167:189.952515:176.336929:128.566925
45168:190.027664:176.350189:128.589233
45169:190.106842:176.343262:128.586151
45170:190.178207:176.346725:128.571152
45171:190.254242:176.344238:128.609238
45172:190.337982:176.344040:128.615005
45173:190.434250:176.349228:128.603073
45174:190.541901:176.347504:128.617691
45175:190.638351:176.354233:128.620193
45176:190.715103:176.349045:128.616150
45177:190.775146:176.348465:128.631927
45178:190.820145:176.226151:128.631546
45179:190.863373:175.937698:128.628082
45180:190.901459:175.677109:128.633850
45181:190.931946:175.566544:128.632690
45182:190.956482:175.657303:128.631729
45183:190.996674:175.895966:128.634613
45184:191.035110:176.156738:128.642502
45185:191.063370:176.278656:128.641724
45186:191.082504:176.332306:128.640961
45187:191.091019:176.332123:128.645187
45188:191.089905:176.332504:128.638458
45189:191.076874:176.330963:128.640579
45190:191.046478:176.329620:128.644623
45191:191.009094:176.334427:128.639038
45192:190.980240:176.332886:128.644424
45193:190.956970:176.336349:128.642502
45194:190.925079:176.334610:128.641724
45195:190.883408:176.342300:128.641541
45196:190.815201:176.349426:128.645966
45197:190.726791:176.344620:128.572495
45198:190.634995:176.354996:128.581726
45199:190.534286:176.355194:128.582123
45200:190.473267:176.351532:128.574615
45201:190.434189:176.348846:128.607498
45202:190.392517:176.359619:128.618073
45203:190.361267:176.354416:128.599426
45204:190.353836:176.358078:128.612122
45205:190.358490:176.361343:128.616150
45206:190.383911:176.358078:128.610199
45207:190.426773:176.355194:128.620193
45208:190.465073:176.356354:128.629425
45209:190.504791:176.356354:128.628647
45210:190.558624:176.356155:128.637115
45211:190.625275:176.355576:128.633469
45212:190.700821:176.354614:128.637314
45213:190.785797:176.354614:128.647690
45214:190.860092:176.356354:128.650772
45215:190.931107:176.355957:128.647690
45216:191.013870:176.353271:128.652878
45217:191.103668:176.356918:128.660004
45218:191.193054:176.360382:128.653656
45219:191.268097:176.356537:128.657883
45220:191.312469:176.357117:128.660004
45221:191.343170:176.359619:128.652695
45222:191.381180:176.322495:128.656738
45223:191.410202:176.140381:128.662308
45224:191.432922:175.855957:128.657883
45225:191.465195:175.689423:128.659042
45226:191.498077:175.710388:128.655380
45227:191.524979:175.864227:128.561539
45228:191.556839:176.115570:128.565186
45229:191.570999:176.289612:128.579620
45230:191.569595:176.325775:128.568466
45231:191.567719:176.334808:128.603073
45232:191.557129:176.343262:128.612503
45233:191.534805:176.340775:128.602310
45234:191.507614:176.343658:128.616348
45235:191.475998:176.352493:128.617889
45236:191.454071:176.352692:128.613083
45237:191.443512:176.348648:128.619812
45238:191.418167:176.351929:128.639999
45239:191.377808:176.356155:128.625763
45240:191.337433:176.356537:128.635193
45241:191.281876:176.358841:128.634430
45242:191.218842:176.359619:128.630768
45243:191.158310:176.358078:128.631546
45244:191.096024:176.358276:128.627884
45245:191.035187:176.358658:128.636917
45246:190.974045:176.358276:128.634811
45247:190.913071:176.357880:128.649811
45248:190.875122:176.354614:128.640762
45249:190.870056:176.354233:128.644424
45250:190.884338:176.351151:128.651535
45251:190.904617:176.352493:128.648071
45252:190.928467:176.355774:128.652878
45253:190.947540:176.358276:128.654800
45254:190.970596:176.355576:128.646729
45255:191.018463:176.365570:128.646729
45256:191.086731:176.364807:128.645966
45257:191.150299:176.339035:128.566727
45258:191.213867:176.356155:128.594238
45259:191.268280:176.365005:128.589417
45260:191.333176:176.354034:128.581146
45261:191.424561:176.352890:128.606918
45262:191.518158:176.357880:128.611343
45263:191.592850:176.351532:128.596725
45264:191.646973:176.362686:128.606918
45265:191.686630:176.357315:128.625580
45266:191.722748:176.269226:128.616730
45267:191.759460:176.009811:128.625198
45268:191.797531:175.700775:128.632309
45269:191.826691:175.537689:128.631729
45270:191.858322:175.560379:128.640961
45271:191.875992:175.774994:128.644424
45272:191.880981:176.024033:128.641724
45273:191.879166:176.234802:128.648270
45274:191.861572:176.328461:128.654236
45275:191.829880:176.350006:128.649811
45276:191.794846:176.349609:128.660767
45277:191.751511:176.355194:128.662888
45278:191.687073:176.355377:128.658844
45279:191.625168:176.352493:128.659042
45280:191.565826:176.357117:128.655960
45281:191.507935:176.355576:128.657883
45282:191.453140:176.354614:128.655762
45283:191.378342:176.354813:128.657883
45284:191.280533:176.355377:128.653275
45285:191.163925:176.360001:128.658463
45286:191.040131:176.361542:128.657700
45287:190.891571:176.333466:128.565964
45288:190.780746:176.351929:128.579620
45289:190.695923:176.348083:128.590378
45290:190.616837:176.350006:128.575378
45291:190.543274:176.346161:128.599045
45292:190.477264:176.345200:128.610580
45293:190.431091:176.343842:128.598267
45294:190.415359:176.347687:128.606354
45295:190.417816:176.346924:128.617310
45296:190.429092:176.348648:128.614807
45297:190.446274:176.350006:128.616150
45298:190.463531:176.350571:128.626541
45299:190.487213:176.346924:128.619232
45300:190.537750:176.350006:128.622116
45301:190.606720:176.360580:128.630386
45302:190.676544:176.360382:128.630386
45303:190.749466:176.360199:128.650955
45304:190.822327:176.359802:128.648270
45305:190.907928:176.357315:128.643082
45306:191.008347:176.357697:128.644806
45307:191.099289:176.352890:128.651917
45308:191.161453:176.337891:128.615005
45309:191.200241:176.205383:128.612122
45310:191.222427:175.860580:128.609238
45311:191.237045:175.517685:128.601349
45312:191.247955:175.301926:128.614609
45313:191.259354:175.343460:128.625961
45314:191.261307:175.597687:128.621536
45315:191.258759:175.841156:128.627304
45316:16.000088:228.565765:199.601730
45317:16.000000:228.565765:199.601730
45318:16.000000:228.565765:199.601730
45319:16.000000:228.565765:199.601730
45320:16.000000:228.565765:199.601730
45321:16.000000:228.565765:199.601730
45322:16.000000:228.565765:199.601730
45323:16.000000:228.565765:199.601730
45324:16.000000:228.565765:199.601730
45325:16.000000:228.565765:199.601730
45326:16.000000:228.565765:199.601730
45327:16.000000:228.565765:199.601730
45328:16.000000:228.565765:199.601730
45329:16.000000:228.565765:199.601730
45330:16.000000:228.565765:199.601730
45331:16.000000:228.565765:199.601730
45332:16.000000:228.565765:199.601730
45333:16.000000:228.565765:199.601730
45334:16.000000:228.565765:199.601730
45335:16.000000:228.565765:199.601730
45336:16.000000:228.565765:199.601730
45337:16.000000:228.565765:199.601730
45338:16.000000:228.565765:199.601730
45339:16.000000:228.565765:199.601730
45340:16.000000:228.565765:199.601730
45341:16.000000:228.565765:199.601730
45342:16.000000:228.565765:199.601730
45343:16.000000:228.565765:199.601730
45344:16.000000:228.565765:199.601730
45345:16.000000:228.565765:199.601730
45346:16.000000:228.565765:199.601730
45347:16.000000:228.565765:199.601730
45348:16.000000:228.565765:199.601730
45349:16.000000:228.565765:199.601730
45350:16.000000:228.565765:199.601730
45351:16.000000:228.565765:199.601730
45352:16.000000:228.565765:199.601730
45353:16.000000:228.565765:199.601730
45354:16.000000:228.565765:199.601730
45355:16.000000:228.565765:199.601730
45356:16.000000:228.565765:199.601730
45357:16.000000:228.565765:199.601730
45358:16.000000:228.565765:199.601730
45359:16.000000:228.565765:199.601730
45360:16.000000:228.565765:199.601730
45361:16.000000:228.565765:199.601730
45362:16.000000:228.565765:199.601730
45363:16.000000:228.565765:199.601730
45364:16.000000:228.565765:199.601730
45365:16.000000:228.565765:199.601730
45366:16.000000:228.565765:199.601730
45367:16.000000:228.565765:199.601730
45368:16.000000:228.565765:199.601730
45369:16.000000:228.565765:199.601730
45370:16.000000:228.565765:199.601730
45371:16.000000:228.565765:199.601730
45372:16.000000:228.565765:199.601730
45373:16.000000:228.565765:199.601730
54058:166.312271:132.029236:190.287308
54059:167.119553:130.865768:185.454224
54060:167.090149:130.688263:185.453262
54061:167.960114:130.617889:189.662109
54062:167.918228:130.592117:189.654037
54063:169.059830:130.544998:189.252121
54064:169.152802:130.553268:189.263077
54065:169.978119:130.558075:189.572311
54066:170.665985:131.503464:187.319611
54067:170.686508:131.448654:187.328659
54068:172.359619:130.549622:188.518646
54069:172.371872:130.551147:188.520187
54070:174.597305:130.415771:187.039032
54071:174.617569:130.417496:187.043274
54072:175.740448:130.331543:186.166351
54073:175.775299:130.331543:186.158661
54074:175.915833:130.335968:184.888077
54075:176.031021:130.330383:184.887695
54076:176.641006:130.338272:182.661545
54077:176.744095:130.356155:182.652695
54078:178.372742:130.383469:180.559616
54079:178.424316:130.369034:180.558273
54080:178.920700:130.320770:179.056351
54081:179.158371:130.359619:178.879044
54082:179.182281:130.338654:178.880005
54083:181.081238:130.288467:177.674622
54084:181.152588:130.281540:177.684814
54085:183.157928:130.247116:176.786148
54086:183.220993:130.250961:176.783463
54087:183.695511:130.256546:178.855377
54088:183.651016:130.259033:178.856918
54089:183.514160:130.154999:178.475571
54090:183.585648:130.155960:178.497498
54091:184.119339:130.151917:177.965775
54092:184.185867:130.153656:177.965195
54093:185.391937:130.145767:177.512314
54094:185.356613:130.150391:177.507111
54095:185.198746:130.182892:177.092117
54096:185.597168:130.390961:176.790573
54097:185.626709:130.379425:176.778458
54098:187.062988:130.153458:176.635773
54099:187.097046:130.148849:176.638077
54100:188.405792:130.038651:176.527313
54101:188.435059:130.035385:176.521927
54102:188.586151:130.019043:176.440384
54103:188.637573:129.998459:176.453262
54104:188.707565:130.001923:176.606918
54105:188.752136:130.000961:176.613083
54106:189.002396:129.982117:176.968658
54107:189.076263:129.977890:176.973465
54108:189.748764:130.058273:177.184036
54109:189.796494:130.039612:177.201340
54110:189.741425:130.006729:177.308655
54111:190.435257:129.925766:177.650772
54112:190.455536:129.910965:177.668076
54113:191.947678:129.876343:177.860580
54114:191.974548:129.873657:177.860580
54115:192.649292:129.797501:177.993271
54116:192.705231:129.781342:177.995193
54117:193.059692:129.757309:177.834808
54118:193.149673:129.756729:177.823654
54119:193.349930:129.757690:177.533661
54120:193.416931:129.767303:177.539032
54121:193.949493:129.735199:177.179611
54122:194.016022:129.733459:177.184036
54123:194.001724:129.697891:176.895966
54124:194.005096:129.675766:176.889420
54125:194.005096:129.675766:176.889420

こんな感じの解析データが入る。


これを、適当だけどプログラムで解析する。

        private void AT_X_CMCut(string OrgName, string AVSName, string M2VFile, string WavFile)
        {
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("*****************************");
            Console.WriteLine("   AT-XのCMカット");
            Console.WriteLine("*****************************");


            string infotxt = Path.Combine(Path.GetDirectoryName(OrgName), Path.GetFileNameWithoutExtension(OrgName) + "_info.txt");
            
            /// 1.画面を検出してその内容を書き出す
            /// AVS2AVIでnull出力にする。
            string AT_X_CMCUT = ReadFile(@"O:\PT2\Encoder\avisynth\postfilterAT-XCMCut.txt");
            string PREFILTER = ReadFile(Settings.Default.PreFilterPath);
            string TEMPLATE = ReadFile(Settings.Default.FilterTemplatePath);

            double threshold0 = 16.1;
            double threshold1 = 135;
            double threshold2 = 135;


            TEMPLATE = TEMPLATE.Replace("#REPKEY_1#", PREFILTER);
            TEMPLATE = TEMPLATE.Replace("#REPKEY_20#", AT_X_CMCUT);

            TEMPLATE = TEMPLATE.Replace("%m2v", M2VFile);
            TEMPLATE = TEMPLATE.Replace("%wav", WavFile);
            TEMPLATE = TEMPLATE.Replace("%fb", @"O:\PT2\Encoder\avisynth\at-x_begin.bmp");
            TEMPLATE = TEMPLATE.Replace("%fe", @"O:\PT2\Encoder\avisynth\at-x_end.bmp");
            TEMPLATE = TEMPLATE.Replace("%ff", infotxt);
            TEMPLATE = TEMPLATE.Replace("%t0", threshold0.ToString());
            TEMPLATE = TEMPLATE.Replace("%t1", threshold1.ToString());
            TEMPLATE = TEMPLATE.Replace("%t2", threshold2.ToString());

            string TESTAVS = OrgName + ".cmcut.avs";
            WriteFile(TESTAVS, TEMPLATE);

            if (!File.Exists(infotxt))
            {
                Exec(@"o:\pt2\encoder\avs2avi.exe", "\"" + TESTAVS + "\" -o n -c null");
            }

            

            /// 2.作られたtxtファイルに基づいて、データを作る。
            string[] lines = ReadFile(infotxt).Split(new string[]{"\r\n"}, StringSplitOptions.RemoveEmptyEntries);
            List<FrameData> frameDataList = new List<FrameData>();
            
            
            foreach (string s in lines)
            {
                string[] items = s.Split(':');
                int frame = 0;
                int type = -1; /// type=0...luma, 1...luma1, 2...luma2
                double luma, luma1, luma2;
                frame = int.Parse(items[0]);
                luma = double.Parse(items[1]);
                luma1 = double.Parse(items[2]);
                luma2 = double.Parse(items[3]);
                if (luma1 < 135 && luma1 > 127) type = 1;
                if (luma2 < 135 && luma2 > 127) type = 2;
                if (luma <= 16.1) type = 0;
                if (type == -1) continue;

                FrameData fd = new FrameData();
                fd.Frame = frame;
                fd.Type = type;
                frameDataList.Add(fd);
            }

            frameDataList.Sort((a, b) => a.Frame - b.Frame);

            /// trim(A, B)を生成する。
            /// Type 1 -> 0 ... ここが始まりのサイン。0が終わった次のフレームから切り取る -> A
            /// Type 0 -> 2 ... ここが終わりのサイン。0が始まった前のフレームまで切り取る -> B


            /// CurrentState 
            /// 0... 1->0を探す
            /// 1... 1->0のあと、0の終わりを探す
            /// 2... 0->2を探す
            int CurrentState = 0;

            string TrimStr = "";

            for (int i = 1; i < frameDataList.Count; i++)
            {
                /// 1->0 ここから開始の予定
                if (CurrentState == 0 && frameDataList[i - 1].Type == 1 && frameDataList[i].Type == 0)
                {
                    CurrentState = 1;
                }

                if (CurrentState == 1 && (frameDataList[i].Type != 0 || frameDataList[i].Frame - frameDataList[i - 1].Frame > 5))
                {
                    if (TrimStr != "") TrimStr += " ++ ";
                    TrimStr += "trim(" + (frameDataList[i - 1].Frame + 1) + ",";
                    CurrentState = 2;
                }

                if (CurrentState == 2 && frameDataList[i - 1].Type == 0 && frameDataList[i].Type == 2)
                {
                    for (int j = i - 1; j > 0; j--)
                    {
                        if ( frameDataList[j].Frame - frameDataList[j - 1].Frame > 5 || frameDataList[j - 1].Type != 0)
                        {
                            TrimStr += frameDataList[j].Frame - 1 + ")";
                            CurrentState = 0;
                            break;
                        }
                    }
                }
                
            }


            /// Trimがうまくいっていなかったとき
            if (CurrentState != 0 && CurrentState != 1)
            {
                TrimStr = TrimStr.Substring(0, TrimStr.LastIndexOf("++"));
            }

            Console.WriteLine("CMカット:" + TrimStr);
            WriteFile(AVSName, ReadFile(AVSName).Replace("#REPKEY_11#", TrimStr));


        }

1.はavsのスクリプト生成。
2.以降がそれ。かなり適当。
フレームの状態を、

  • -1 それ以外のフレーム
  • 0 真っ黒なフレーム
  • 1 begin.bmpとほとんどおなじフレーム
  • 2 end.bmpとほとんどおなじフレーム

と定義する。

コメントにあるように1->0となったところが始まり、0->2となったところが終わりとして、Trimコマンドを生成する。

これでまあまあ精度良く自動カットできました。