blob: 86e25f4cdc95e4f040510b839fc74ab450dfa5f7 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/projector/projector_metadata_controller.h"
#include "ash/constants/ash_features.h"
#include "ash/projector/projector_metadata_model.h"
#include "ash/projector/projector_metrics.h"
#include "ash/projector/projector_ui_controller.h"
#include "ash/webui/projector_app/public/cpp/projector_app_constants.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/task/current_thread.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "third_party/icu/source/common/unicode/locid.h"
namespace ash {
namespace {
// Writes the given |data| in a file with |path|. Returns true if saving
// succeeded, or false otherwise.
bool SaveFile(const std::string& content, const base::FilePath& path) {
DCHECK(!base::CurrentUIThread::IsSet());
DCHECK(!path.empty());
if (!base::PathExists(path.DirName()) &&
!base::CreateDirectory(path.DirName())) {
LOG(ERROR) << "Failed to create path: " << path.DirName();
return false;
}
return base::WriteFile(path, content);
}
const std::string GetFormattedLangauge(const icu::Locale& locale) {
const std::string language = locale.getLanguage();
if (language == "zh") {
return "zh_TW";
}
return language;
}
} // namespace
ProjectorMetadataController::ProjectorMetadataController() = default;
ProjectorMetadataController::~ProjectorMetadataController() = default;
void ProjectorMetadataController::OnRecordingStarted() {
metadata_ = std::make_unique<ProjectorMetadata>();
metadata_->SetCaptionLanguage(
GetFormattedLangauge(icu::Locale::getDefault()));
if (ash::features::IsProjectorV2Enabled()) {
metadata_->SetMetadataVersionNumber(MetadataVersionNumber::kV2);
}
}
void ProjectorMetadataController::RecordTranscription(
const media::SpeechRecognitionResult& speech_result) {
DCHECK(metadata_);
const auto& timing = speech_result.timing_information;
metadata_->AddTranscript(std::make_unique<ProjectorTranscript>(
timing->audio_start_time, timing->audio_end_time,
/*group_id=*/timing->audio_start_time.InMilliseconds(),
speech_result.transcription, timing->hypothesis_parts.value()));
}
void ProjectorMetadataController::SetSpeechRecognitionStatus(
RecognitionStatus status) {
DCHECK(metadata_);
metadata_->SetSpeechRecognitionStatus(status);
}
void ProjectorMetadataController::RecordKeyIdea() {
DCHECK(metadata_);
metadata_->MarkKeyIdea();
}
void ProjectorMetadataController::SaveMetadata(
const base::FilePath& video_file_path) {
DCHECK(metadata_);
// TODO(b/200330118): Finalize on the metadata file naming convention.
const base::FilePath path = video_file_path.AddExtension(
ash::features::IsProjectorV2Enabled() ? kProjectorV2MetadataFileExtension
: kProjectorMetadataFileExtension);
// Save metadata.
auto metadata_str = metadata_->Serialize();
// TODO(b/203000496): Update after finalizing on the storage strategy.
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock()},
base::BindOnce(&SaveFile, metadata_str, path),
base::BindOnce(&ProjectorMetadataController::OnSaveFileResult,
weak_factory_.GetWeakPtr(), path,
metadata_->GetTranscriptsCount()));
}
void ProjectorMetadataController::OnSaveFileResult(const base::FilePath& path,
size_t transcripts_count,
bool success) {
if (!success) {
LOG(ERROR) << "Failed to save the metadata file: " << path;
ProjectorUiController::ShowSaveFailureNotification();
return;
}
RecordTranscriptsCount(transcripts_count);
}
void ProjectorMetadataController::SetProjectorMetadataModelForTest(
std::unique_ptr<ProjectorMetadata> metadata) {
metadata_ = std::move(metadata);
}
} // namespace ash