仕事の備忘録

IT系技術とか、カスタマーサービスとか

ffmpegとC#を使って指定秒数の音声ファイルを作る 1.ざっくり設計

前回ffmpegを使ってDOSコマンドで音声変換を行った。その話を会社でしたら、ある動画からの文字起こしを自動的に行いたいという要望がやってきた。

testedquality-tech.hatenadiary.jp

 文字起こしというのは、インタビューなどの会話を録音し、あとから文字として文書化することの総称。結構な手間がかかり専門の業者がたくさんある。そしてこちらでは専用アプリでの音声文字変換による支援サービスを提供中。

voxt.jp

この会社が行っているような、自動化をもっと手軽に自社でできないかという相談だ。これができるようになると、自分の周りで行っている通常の電話応対や、インタビューなども文字起こしして、検索データベース化したり、資料保存の作業低減ができるかもしれない。そんな気持ちから対応することになった。

前回試してみた「Bing Speech API」を使うとなると最大2分までしか一度に翻訳できない。そうなるとバッチコマンドを並べて一括処理でAPI最大処理分数である2分の動画を切り出せはよいと考えたが、実際にバッチで切り出してみたところ、話の途中で切れると、API側で話の前後の内容が正しく理解できず変な文章が戻ってくる。

イメージとしてはYoutubeで自動文字起こしがついているとき。多分あれもgoogleの日本語文字起こしが自動的に行われている。動画の登録時のオプションで設定できるのだが切れ切れの文字起こしはわかりづらい(この場合話し言葉を聞き取れてないのもあるのだが)サンプル動画はこちら。

www.youtube.com

Youtube.comのサイトにて動画を見ると画面左下のメニュー「その他」の中に「文字起こし」というメニューが出てくる。これがgoogleが自動文字起こしをした結果を表示させている。

 

これを見る限り、文として完結している、読点が付いた秒数で音声ファイルを切り出さないといけないことが分かった。単純に2分毎に切断というわけにはいかないのであった。当たり前なのだけど、APIに処理させることばかり考えてた。反省。

まずは後から秒数を指定できるように、秒数をインプットで可変で対応できるようにしてffmpegで指定秒数切り出しを実施することにした。前回バッチプログラムを出力する方針にしていたが、自動的に切り出すプログラムを作るように変更する。

秒数のインプット形式はCSVにすることを決めた。今回仕事の依頼者がサーバ持ってなかったので手軽な方法を選択。CSVをC#で扱う手段は調べたらたくさんあったが、.Net 2.0の方法などが検索上位に出てくる。やりたいことはできるが納得いかず。ググった末に見つけたのは、NuGet取得できてメンテナンスもされてて初心者な自分でも使いやすかったこちら。ありがたしLINQ to CSV。

devlights.hatenablog.com

 ffmpegはDOSでの処理を行っている。DOSをC#から使う方法は検索したところ、ffmpegを使ったサンプルがすでに書かれていたのでありがたく参照。

blog.shibayan.jp

 これでやりたいことはできそうな見通しが立ったのでプログラムを書くことにした。

★インプットのCSV設定

CSVには切り出す秒数の開始時点と、そのあとの秒数を設定。前2つはDB化した場合のキー項目、ファイル名と連番を指定。

「きちんと順番に項目を並べてないのは気持ち悪いぞ!」と自分でも思うがプログラムしながら項目並べたらこんな感じに。LINQ to CSVを使えば項目指定もできるので不便はそこまで感じない。

こんなクラスを準備して、指定CSVを読み出すメソッドを下記のように準備できる。ありがたい。
    class CSVData
    {
        [CsvColumn(FieldIndex = 1)]
        public string Id { get; set; }
        [CsvColumn(FieldIndex = 2)]
        public string Name { get; set; }
        [CsvColumn(FieldIndex = 3)]
        public int startsec { get; set; }
        [CsvColumn(FieldIndex = 4)]
        public int vframessec { get; set; }

    }

   

/// <summary>
/// asa 処理ファイル作成
/// </summary>
/// <returns>List型のCSVデータセット</returns>
/// <param name="csvpath">読み取るCSVファイルパス</param>

    private List<CSVData> setCSV(string csvpath)
        {
            //
            // LINQ to CSVのサンプル.
            //   元ネタ: http://www.codeproject.com/Articles/25133/LINQ-to-CSV-library
            // 
            // LINQ to CSVはNuGetでインストールできる.
            //   Install-Package LINQToCSV
            
            // コンテキストを構築.
            var context = new CsvContext();

            //
            // CSVの情報を示すオブジェクトを構築.
            //
            var description = new CsvFileDescription
            {
                SeparatorChar = ',',
                FirstLineHasColumnNames = false,
                EnforceCsvColumnAttribute = true,
                TextEncoding = Encoding.UTF8
            };

            //
            // 読み取り.
            //
            var dataList = context.Read<CSVData>(csvpath, description).ToList();

           return dataList;

        }

.