Как извлечь расшифровку стенограммы с несколькими выступающими из вывода JSON с расшифровкой речи Google Video Intelligence API с помощью jq?

Я тестирую преобразование речи в текст Google Video Intelligence для расшифровки эпизодов подкастов с несколькими динамиками.

Я извлек пример и опубликовал его в gist: output.json.

cat file.json | jq '.response.annotationResults[].speechTranscriptions[].alternatives[] | {startTime: .words[0].startTime, segment: .transcript }'

Команда выше распечатает startTimeкаждого сегмента вместе с самим сегментом. jq-output.json

{
  "time": "6.400s",
  "segment": "Hi, my name is Melinda Smith from Noble works. ...snip"
}
{
  "time": "30s",
  "segment": " Any Graham as a tool for personal and organizational ...snip"
}

Я стремлюсь к тому, чтобы speakerTagдля каждого сегмента, включенного в мой вывод jq.

Вот где я застрял... для начала, каждый массив внутри .alternatives[] содержит .transcript строка, содержащая этот сегмент, .confidence, а также .words[] массив с каждым словом этого сегмента и временем его произнесения.

Эта часть JSON - это то, как я получаю первую часть вывода. Затем, после того, как он прошел через каждый сегмент расшифровки стенограммы, внизу будет один последний.alternatives[] массив, содержащий (снова) каждое слово из всей транскрипции, по одному, вместе с его startTime, endTime и SpeakerTag.

Вот упрощенный пример того, что я имею в виду:

speechTranscriptions:
  alternatives:
    transcript: "Example transcript segment"
    words:
      word: "Example"; startTime: 0s;
      word: "transcript"; startTime: 1s;
      word: "segment"; startTime: 2s;
  alternatives:
    transcript: "Another transcript segment"
    words:
      word: "Another"; startTime: 3s;
      word: "transcript"; startTime: 4s;
      word: "segment"; startTime: 5s;
  alternatives:
    words:
      word: "Example"; startTime: 0s; speakerTag: 1;
      word: "transcript"; startTime: 1s; speakerTag: 1;
      word: "segment"; startTime: 2s; speakerTag: 1;
      word: "Another"; startTime: 3s; speakerTag: 2;
      word: "transcript"; startTime: 4s; speakerTag: 2;
      word: "segment"; startTime: 5s; speakerTag: 2;

Я думал как-то пройти через jq-output.json и сопоставить каждыйstartTime с соответствующим speakerTag найдено в исходном выводе Video Intelligence API.

.response.annotationResults[].speechTranscriptions[].alternatives[] | ( if .words[].speakerTag then {time: .words[].startTime, speaker: .words[].speakerTag} else empty end)

Я попробовал несколько вариантов этого, с идеей распечатать только время начала и динамик Tag, а затем сопоставить значения на моем следующем шаге. Моя проблема заключалась в том, что я не понимал, как распечатать startTime, только если у него есть соответствующий SpeakerTag.

Как упоминалось в комментариях, было бы предпочтительнее генерировать этот результат в одной команде, но я просто пытался разбить проблему на части, которые я мог бы попытаться понять.

1 ответ

Решение

Моя проблема заключалась в том, что я не понимал, как распечатать startTime, только если у него есть соответствующий SpeakerTag.

Это можно сделать с помощью фильтра:

.response.annotationResults[].speechTranscriptions[].alternatives[].words[]
 | select(.speakerTag)
 | {time: .startTime, speaker: .speakerTag}

Так что, возможно, следующее решение (или, по крайней мере, близкое к решению) основной проблемы:

.response.annotationResults[].speechTranscriptions[].alternatives[]
| (INDEX(.words[] | select(.speakerTag); .startTime) | map_values(.speakerTag)) as $dict
| {startTime: .words[0].startTime, segment: .transcript}
| . + {speaker: $dict[.startTime]}
Другие вопросы по тегам