vtt ファイルからテキストを取得する

vtt ファイルからテキストを取得する

vtt ファイルは次のようになります:

WEBVTT

1
00:00:00.096 --> 00:00:05.047
you're the four functions if you would of 
management first of all you have the planning

2
00:00:06.002 --> 00:00:10.079
the planning stages basically you were choosing appropriate 
 organizational goals and courses

3
00:00:11.018 --> 00:00:13.003
action to best achieve those goals

次のようなテキストだけが必要です:

you're the four functions if you would of management first of all you have the planning the planning stages basically you were choosing appropriate organizational goals and courses action to best achieve those goals

Ubuntuで試してみました:

cat file.vtt | grep -v [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9][[:space:]][[:punct:]][[:punct:]][[:punct:]][[:space:]][0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]

つまり、次のようになります:

WEBVTT

1
you're the four functions if you would of 
management first of all you have the planning

2
the planning stages basically you were choosing appropriate 
 organizational goals and courses

3
action to best achieve those goals

しかし、残りの部分をどうすればよいのかわかりません。私が置き換えたいのは

\n[0-9]+\n\nスペースを入れたいのですが、sed や grep でそれを実行させる方法がわかりません。

基本/ポータブル(たとえば、Ubuntu、CentOS などに一般的にプリインストールされている、grep、sed、tr コマンドなど)を使用して、字幕のタイミングを削除した生のテキストだけを 1 行(改行なし)にするにはどうすればよいですか?

注: これは中国語、ヒンディー語、アラビア語などの他の言語の文字でも機能する必要があるため、[az] タイプの一致は避け、代わりに形式が非常に一貫しているタイミング ラインを削除します。また、テキストには数字が含まれる可能性があるため、数字を盲目的に削除しないでください。

注2: 最終的な目標は、テキストをJSON値として安全にすることです。そのため、すべての特殊文字が削除され、二重引用符がエスケープされますが、これはこの質問の範囲を超えています。

答え1

あなたのファイルは1行以上の空白行で区切られたレコードのシーケンスで構成されているようですので、段落モードまたは のいずれawkperl

たとえば、常に最初の2行を削除する必要がある場合、

1
00:00:00.096 --> 00:00:05.047

空白で区切られた段落内の改行で区切られたフィールドに分割し、最初の2つのフィールドをスキップすることができます。

awk -vRS= -vORS= -F'\n' '{for(j=3;j<=NF;j++) print $j; print " "}' file.vtt

または

perl -F'\n' -00ne 'print join("", @F[2..$#F]), " "' file.vtt

削除するフィールド(行)の数が固定されているとは限らない場合、正規表現テストを追加するのはかなり簡単です。明示的なループを記述するのではなく、配列に直接perl適用できるため、少し簡単にgrepなります。たとえば、空白で区切られたレコードに分割し、少なくとも3つのアルファベット文字のシーケンスを含むフィールド(行)のみを印刷するには、次のようにします。

perl -F'\n' -00ane '
  print join("", grep { /[[:alpha:]]{3}/ } @F), " "
' file.vtt

文字列を除外したい場合はWEBVTT、最初のレコードをスキップするだけです。

perl -F'\n' -00ane '
  print join("", grep { /[[:alpha:]]{3}/ } @F), " " if $. > 1
  ' file.vtt

必要な行をキャプチャし、不要な行を除外する適切な正規表現を選択するのはあなた次第です。連結された出力に最後の改行を追加する場合は、または のENDいずれかにブロックを追加できます。awkperl


注: (コメントでの議論に基づくと) ファイルは DOS 形式の行末を持っているように見えるため、上記のコマンドでフィールドとレコードの区切り文字を適宜変更するか、最初に s をCRLF削除して対処する必要があります。例:CR

sed 's/\r$//' file.vtt | 
  perl -F'\n' -00ane '
    print join("", grep { /[[:alpha:]]{3}/ } @F), " " if $. > 1
  '
you're the four functions if you would of management first of all you have the planning the planning stages basically you were choosing appropriate  organizational goals and courses action to best achieve those goals steeldriver@xenial-vm:~/test/$

答え2

さて、これが私の最終的な結果です

#!/bin/bash
fname=$1
sed 's/\r$//' "$fname"    |\
grep -v -- "-->"          |\
grep -v "^$"              |\
grep -E -v "^[0-9]+$"     |\
sed 's/WEBVTT//'          |\
tr '\n' ' '               |\
tr -s ' '                 |\
tr -d '\t'                |\
sed 's/\\/\\\\/g'         |\
sed 's/"/\\"/g' 
  1. Windowsの改行を修正
  2. --> を含まないすべての行を検索します。
  3. 空でない行をすべて検索します(これがより速いと思いますが、そうでないかもしれません)
  4. 数字だけではないすべての行を見つける
  5. WEBVTTヘッダーを削除
  6. 改行を削除する
  7. 複数のスペースを1つにまとめる
  8. タブを削除
  9. バックスラッシュをエスケープする(JSON の場合)
  10. 二重引用符をエスケープする(JSON の場合)

Windows の改行を修正してくれた @steeldriver に感謝します。

これは少し弱いので、本番環境では使用しません。たとえば、「あなたは --> 私の友達です」などのテキスト行をスキップしたり、おそらく他のいくつかのケースをスキップしたりしますが、私の目的 (検索のために Solr に投稿する) には十分なはずです。

ただし、かなり非効率的であることはわかっています。その点についてアドバイスをいただければ幸いです。

関連情報