projector_metadata_model.cc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/projector/projector_metadata_model.h"
  5. #include "base/json/json_writer.h"
  6. #include "base/logging.h"
  7. #include "base/strings/string_number_conversions.h"
  8. #include "base/values.h"
  9. #include "media/mojo/mojom/speech_recognition.mojom.h"
  10. namespace ash {
  11. namespace {
  12. using base::ListValue;
  13. using base::Value;
  14. constexpr base::StringPiece kStartOffsetKey = "startOffset";
  15. constexpr base::StringPiece kEndOffsetKey = "endOffset";
  16. constexpr base::StringPiece kTextKey = "text";
  17. constexpr base::StringPiece kHypothesisPartsKey = "hypothesisParts";
  18. constexpr base::StringPiece kCaptionLanguage = "captionLanguage";
  19. constexpr base::StringPiece kCaptionsKey = "captions";
  20. constexpr base::StringPiece kKeyIdeasKey = "tableOfContent";
  21. constexpr base::StringPiece kOffset = "offset";
  22. base::Value HypothesisPartsToValue(
  23. const media::HypothesisParts& hypothesis_parts) {
  24. base::Value text_value(base::Value::Type::LIST);
  25. for (auto& part : hypothesis_parts.text)
  26. text_value.Append(part);
  27. base::Value hypothesis_part_value(base::Value::Type::DICTIONARY);
  28. hypothesis_part_value.SetKey(kTextKey, std::move(text_value));
  29. hypothesis_part_value.SetIntKey(
  30. kOffset, hypothesis_parts.hypothesis_part_offset.InMilliseconds());
  31. return hypothesis_part_value;
  32. }
  33. } // namespace
  34. MetadataItem::MetadataItem(const base::TimeDelta start_time,
  35. const base::TimeDelta end_time,
  36. const std::string& text)
  37. : start_time_(start_time), end_time_(end_time), text_(text) {}
  38. MetadataItem::~MetadataItem() = default;
  39. ProjectorKeyIdea::ProjectorKeyIdea(const base::TimeDelta start_time,
  40. const base::TimeDelta end_time,
  41. const std::string& text)
  42. : MetadataItem(start_time, end_time, text) {}
  43. ProjectorKeyIdea::~ProjectorKeyIdea() = default;
  44. // The JSON we generate looks like this:
  45. // {
  46. // "startOffset": 100
  47. // "endOffset": 2100
  48. // "text": "Today I'd like to teach..."
  49. // }
  50. //
  51. // Which is:
  52. // DICT
  53. // "startOffset": INT
  54. // "endOffset": INT
  55. // "text": STRING
  56. base::Value ProjectorKeyIdea::ToJson() {
  57. base::Value transcript(base::Value::Type::DICTIONARY);
  58. transcript.SetIntKey(kStartOffsetKey, start_time_.InMilliseconds());
  59. transcript.SetIntKey(kEndOffsetKey, end_time_.InMilliseconds());
  60. transcript.SetStringKey(kTextKey, text_);
  61. return transcript;
  62. }
  63. ProjectorTranscript::ProjectorTranscript(
  64. const base::TimeDelta start_time,
  65. const base::TimeDelta end_time,
  66. const std::string& text,
  67. const std::vector<media::HypothesisParts>& hypothesis_parts)
  68. : MetadataItem(start_time, end_time, text),
  69. hypothesis_parts_(hypothesis_parts) {}
  70. ProjectorTranscript::~ProjectorTranscript() = default;
  71. // The JSON we generate looks like this:
  72. // {
  73. // "startOffset": 100
  74. // "endOffset": 2100
  75. // "text": "Today I would like to teach..."
  76. // "hypothesisParts": [
  77. // {
  78. // "text": ["Today"]
  79. // "offset": 100
  80. // },
  81. // {
  82. // "text": ["I"]
  83. // "offset": 200
  84. // },
  85. // ...
  86. // ]
  87. // }
  88. //
  89. // Which is:
  90. // DICT
  91. // "startOffset": INT
  92. // "endOffset": INT
  93. // "text": STRING
  94. // "hypothesisParts": DICT LIST
  95. //
  96. base::Value ProjectorTranscript::ToJson() {
  97. base::Value transcript(base::Value::Type::DICTIONARY);
  98. transcript.SetIntKey(kStartOffsetKey, start_time_.InMilliseconds());
  99. transcript.SetIntKey(kEndOffsetKey, end_time_.InMilliseconds());
  100. transcript.SetStringKey(kTextKey, text_);
  101. base::Value hypothesis_parts_value(base::Value::Type::LIST);
  102. for (auto& hypothesis_part : hypothesis_parts_)
  103. hypothesis_parts_value.Append(HypothesisPartsToValue(hypothesis_part));
  104. transcript.SetKey(kHypothesisPartsKey, std::move(hypothesis_parts_value));
  105. return transcript;
  106. }
  107. ProjectorMetadata::ProjectorMetadata() = default;
  108. ProjectorMetadata::~ProjectorMetadata() = default;
  109. void ProjectorMetadata::SetCaptionLanguage(const std::string& language) {
  110. caption_language_ = language;
  111. }
  112. void ProjectorMetadata::AddTranscript(
  113. std::unique_ptr<ProjectorTranscript> transcript) {
  114. if (should_mark_key_idea_) {
  115. key_ideas_.push_back(std::make_unique<ProjectorKeyIdea>(
  116. transcript->start_time(), transcript->end_time()));
  117. }
  118. transcripts_.push_back(std::move(transcript));
  119. should_mark_key_idea_ = false;
  120. }
  121. void ProjectorMetadata::MarkKeyIdea() {
  122. should_mark_key_idea_ = true;
  123. }
  124. std::string ProjectorMetadata::Serialize() {
  125. std::string metadata_str;
  126. base::JSONWriter::Write(ToJson(), &metadata_str);
  127. return metadata_str;
  128. }
  129. // The JSON we generate looks like this:
  130. // {
  131. // "captionLanguage": "en"
  132. // "captions": [{
  133. // "startOffset": 100
  134. // "endOffset": 2100
  135. // "text": "Today I'd like to teach you about a central pillar of a
  136. // construction learning theory it's called the debugging Loop...",
  137. // "hypothesisParts": [
  138. // {
  139. // "text" : ["Today"],
  140. // "offset": 100,
  141. // },
  142. // {
  143. // "text": ["I"],
  144. // "offset": 1500,
  145. // }
  146. // ...
  147. // ]
  148. // }],
  149. // "tableOfContent": [
  150. // {
  151. // "endOffset" : 4500,
  152. // "startOffset": 4400,
  153. // "text": "Making a creation",
  154. // },
  155. // ]
  156. // }
  157. //
  158. // Which is:
  159. // DICT
  160. // "@type": STRING
  161. // "text": STRING
  162. // "captions": LIST
  163. // "captionLanguage": STRING
  164. // "tableOfContent": LIST
  165. base::Value ProjectorMetadata::ToJson() {
  166. base::Value metadata(base::Value::Type::DICTIONARY);
  167. metadata.SetStringKey(kCaptionLanguage, caption_language_);
  168. base::Value captions_value(base::Value::Type::LIST);
  169. for (auto& transcript : transcripts_)
  170. captions_value.Append(transcript->ToJson());
  171. metadata.SetKey(kCaptionsKey, std::move(captions_value));
  172. base::Value key_ideas_value(base::Value::Type::LIST);
  173. for (auto& key_idea : key_ideas_)
  174. key_ideas_value.Append(key_idea->ToJson());
  175. metadata.SetKey(kKeyIdeasKey, std::move(key_ideas_value));
  176. return metadata;
  177. }
  178. } // namespace ash