動画からテキストを抽出するプロセスを簡潔に説明します。このプロセスは以下の3つのステップで構成されています:
- 動画ファイルの取得
- 音声の分離
- 音声からテキストへの変換
まず、動画ファイルをダウンロードするためのコードを示します。このコードはURLから動画ファイルをダウンロードし、そのInputStreamを返します。
public InputStream downloadVideo(String videoUrl) {
InputStream videoInputStream = null;
try {
String fileName = "video-" + System.currentTimeMillis() + "-" + UUID.randomUUID().toString() + ".mp4";
File tempFolder = new File("temp");
if (!tempFolder.exists()) {
tempFolder.mkdir();
}
File videoFile = HttpUtil.downloadFileFromUrl(videoUrl, new File(tempFolder, fileName), new StreamProgress() {
@Override
public void start() {
log.info("Start downloading file...");
}
@Override
public void progress(long total) {
// プログレス情報をログに出力
}
@Override
public void finish() {
log.info("File downloaded successfully!");
}
});
videoInputStream = new FileInputStream(videoFile);
videoFile.delete();
} catch (Exception e) {
log.error("Failed to get video stream: {}", videoUrl, e);
throw new BusinessException(ErrorCodeEnum.DOWNLOAD_VIDEO_ERROR.code(), "Failed to get video stream");
}
return videoInputStream;
}
次に、JavaCVを使用して音声を分離するコードです。FFmpegFrameRecorderとFFmpegFrameGrabberを使用して音声データを抽出します。
public ExtractAudioRes extractAudio(InputStream videoInputStream) throws Exception {
ByteArrayOutputStream audioOutputStream = new ByteArrayOutputStream();
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(audioOutputStream, 2);
recorder.setAudioOption("crf", "0");
recorder.setAudioQuality(0);
recorder.setAudioBitrate(256000);
recorder.setSampleRate(8000);
recorder.setFormat("wav");
recorder.setAudioCodec(avcodec.AV_CODEC_ID_PCM_S16LE);
recorder.start();
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoInputStream);
grabber.setSampleRate(8000);
grabber.setOption("stimeout", String.valueOf(TimeUnit.MINUTES.toMicros(30L)));
grabber.start();
recorder.setAudioChannels(grabber.getAudioChannels());
Frame frame;
Long audioTime = grabber.getLengthInTime() / 1000 / 1000;
while ((frame = grabber.grabSamples()) != null) {
recorder.record(frame);
}
grabber.stop();
recorder.close();
ExtractAudioRes result = new ExtractAudioRes(audioOutputStream.toByteArray(), audioTime, audioOutputStream.size() / 1024);
result.setFormat("wav");
return result;
}
最後に、抽出された音声データをテキストに変換するためのコードです。ここではTencent CloudのASR APIを使用しています。
public String convertSpeechToText(byte[] audioData, String format) {
log.info("Starting speech-to-text conversion");
AsrClient client = new AsrClient(cred, "");
SentenceRecognitionRequest request = new SentenceRecognitionRequest();
request.setSourceType(1L);
request.setVoiceFormat(format);
request.setEngSerViceType("16k_zh");
String base64EncodedData = BaseEncoding.base64().encode(audioData);
request.setData(base64EncodedData);
request.setDataLen((long) audioData.length);
String text = "";
try {
SentenceRecognitionResponse response = client.SentenceRecognition(request);
log.info("Speech-to-text result: {}", JSONUtil.toJsonStr(response));
text = response.getResult();
if (Strings.isNotBlank(text)) {
return text;
}
return "No content";
} catch (TencentCloudSDKException e) {
log.error("Speech-to-text conversion failed: {}", e);
throw new BusinessException(AUDIO_RECOGNIZE_ERROR.code(), "Speech-to-text conversion failed, please retry");
}
}
長時間の音声データを処理する場合、以下のようなコードを使用します。
public String convertLongSpeechToText(byte[] audioData, String format) {
log.info("Starting long speech-to-text conversion");
Credential credential = Credential.builder()
.secretId(AppConstant.Tencent.asrSecretId)
.secretKey(AppConstant.Tencent.asrSecretKey)
.build();
String text = "";
try {
FlashRecognizer recognizer = SpeechClient.newFlashRecognizer(AppConstant.Tencent.arsAppId, credential);
FlashRecognitionRequest request = FlashRecognitionRequest.initialize();
request.setEngineType("16k_zh");
request.setFirstChannelOnly(1);
request.setVoiceFormat(format);
request.setSpeakerDiarization(0);
request.setFilterDirty(0);
request.setFilterModal(0);
request.setFilterPunc(0);
request.setConvertNumMode(1);
request.setWordInfo(1);
FlashRecognitionResponse response = recognizer.recognize(request, audioData);
if (SuccessCode.equals(response.getCode())) {
text = response.getFlashResult().get(0).getText();
return text;
}
log.info("Long speech-to-text conversion failed: {}", JSONUtil.toJsonStr(response));
throw new BusinessException(AUDIO_RECOGNIZE_ERROR.code(), "Long speech-to-text conversion failed, please retry");
} catch (Exception e) {
log.error("Speech-to-text conversion failed: {}", e);
throw new BusinessException(AUDIO_RECOGNIZE_ERROR.code(), "Speech-to-text conversion failed, please retry");
}
}
public Boolean isLongAudio(AudioRecognitionReq req) {
if (req.getAudioTime() == null || req.getAudioTime() >= AppConstant.Tencent.Max_Audio_Len || req.getAudioSize() >= AppConstant.Tencent.Max_Audio_Size) {
return true;
}
return false;
}
これらのコードを使って、動画からテキストを抽出する機能を実装することができます。