![[Summer Vacation Independent Research Relay] Comparing Japanese Speech-to-Text Transcription Accuracy Between Amazon Transcribe and faster-whisper](https://devio2024-media.developers.io/image/upload/f_auto,q_auto,w_3840/v1787010609/user-gen-eyecatch/k7mhedscltlspsof4q9l.jpg)
[Summer Vacation Independent Research Relay] Comparing Japanese Speech-to-Text Transcription Accuracy Between Amazon Transcribe and faster-whisper
This page has been translated by machine translation. View original
Introduction
Hello, this is Yonamine from the Osaka office.
This article is the 18th entry in the 『Summer Vacation Independent Research Relay』 by volunteers at Classmethod.
This blog relay series was created by members who regularly follow cloud and AI, with the idea of not only outputting "tried it" but also "built it" and "researched/studied it"!
We hope this will bring new insights as well as contribute ideas to the development of our company and community, so we appreciate your readership!
Lately, I often find myself thinking that I'd like to use audio recordings of meetings and conversations as data sources for AI.
There are many Japanese speech transcription tools out there, but as humans, we naturally want ones that are cheap, fast, and accurate.
On top of that, since I usually work with AWS, it would be even better if it runs on AWS.
I was bouncing ideas with Kiro to find tools that could meet these requirements.
Among the options, Amazon Transcribe and faster-whisper became my top candidates.
So, I was curious about which one provides better accuracy for Japanese speech transcription, and decided to compare them!
For evaluating Japanese transcription accuracy, I consulted with Kiro on the evaluation criteria, and the final verification was done by a human (me).
Preface
Since I didn't have any meeting recordings suitable for a blog post, this article uses audio recorded from a roundtable-style conversation video from our company's YouTube channel instead.
Proper nouns and numbers that would commonly appear in regular meetings are included, so I thought it would be a good subject.
The video is about 19 minutes long, and since it's on YouTube, the audio is fairly easy to hear.
Therefore, I think the conditions for this verification are slightly better than a typical meeting.
Please understand that the verification results are based on the conditions described above.
Conclusion First
Honestly, there was nothing that was the best in every category.
Each had its strengths and areas of concern.
There were trends in transcription errors:
Amazon Transcribe had many omissions and proper noun recognition errors, while faster-whisper had many errors with numbers and English words.
large-v3 had the best accuracy for proper nouns.
Amazon Transcribe had the fewest speaker diarization errors.
Processing time was shortest for large-v3-turbo GPU at 1 minute 7.584 seconds.
It's remarkable that approximately 19 minutes of audio can be processed in about 1 minute.
Amazon Transcribe took 2 minutes 33.640 seconds, which was roughly the same as large-v3 GPU's 2 minutes 27.239 seconds.
The estimated cost was lowest for large-v3-turbo GPU at $0.022047, while Amazon Transcribe was $0.114200.
However, faster-whisper runs on EC2.
The $0.022047 simply converts the time spent on transcription to a cost.
Considering that Amazon Transcribe requires no instance and can be run at any time for only as long as needed, I think a straightforward comparison is difficult.
Verification Details
The verification involves transcribing the same audio in 5 configurations.
faster-whisper was tested in 4 configurations total, running different models on different processors.
| Configuration | Execution Target |
|---|---|
| Amazon Transcribe | ap-northeast-1 |
| faster-whisper large-v3 CPU | c8i.4xlarge |
| faster-whisper large-v3 GPU | g6.xlarge |
| faster-whisper large-v3-turbo CPU | c8i.4xlarge |
| faster-whisper large-v3-turbo GPU | g6.xlarge |
Since faster-whisper itself doesn't appear to have a speaker diarization feature, we combine it with a Python audio processing library called pyannote Community-1.
The evaluation proceeds in 3 steps.
- I watch the video and transcribe the reference text
- Pass the reference text and the 5 configuration outputs to Kiro to have it identify candidate differences
- I compare the candidates identified by Kiro against the reference text
While it's difficult to measure accuracy quantitatively, I consulted with Kiro and categorized items that a human would judge as incorrect.
I also measure processing time and estimated cost (ap-northeast-1).
Execution Environment
The execution environment for faster-whisper is as follows.
Amazon Transcribe is a managed service and is therefore not included.
CPU configuration
- Instance: c8i.4xlarge
- OS: Amazon Linux 2023 (kernel 6.18.39-79.141.amzn2023.x86_64)
- CPU: Intel Xeon 6975P-C, 16 vCPU
- Python: 3.12.13
- uv: 0.11.21
GPU configuration
- Instance: g6.xlarge
- AMI: ami-02661579dcd8efe92 (Deep Learning Base OSS Nvidia Driver GPU AMI (Amazon Linux 2023) 20260807)
- GPU: NVIDIA L4 (23,034 MiB), driver 595.91.07
- CUDA: 12.8 (cuBLAS 12.8.4.1, cuDNN 9.10.2)
- Python: 3.12.13
- uv: 0.11.21
Deciding the Evaluation Method with Kiro
The evaluation method was decided in discussion with Kiro.
I pass each configuration's output and the reference text (human transcription) to Kiro.
Kiro is asked to extract the following candidates by comparing the two.
| Category | Content to Check |
|---|---|
| Misrecognition | Locations where speech was replaced with different text |
| Omission | Locations where speech was not included in transcription |
| Addition | Locations where text not in the audio was added |
| Proper Nouns | Candidates where person names or product names were wrong |
| Numbers/English Words | Candidates where numbers or English words were wrong |
| Speaker Assignment Error | Candidates where the speaker and speaker label don't match |
Proper nouns and numbers/English words are partially counted in overlap with misrecognitions and omissions.
Since I wasn't confident relying solely on Kiro's judgment, I personally verified each location that Kiro identified as an error by comparing it against my own transcription.
Preparing the Verification Audio with Mac's Voice Memos
I played the video on Mac and recorded the sound using Voice Memos.
The reference text was transcribed by me while watching the video.
This was the most tedious part of the work...
To compare at the same level of granularity as the transcription output, I kept fillers such as "etto" and "ma," in the text.
Here is an excerpt from the beginning of the reference text I created.
There are 3 speakers, referred to as Person A, Person B, and Person C.
A
Hello. This is the Classmethod YouTube channel.
Today, since Classmethod is known as a blog company,
on DevelopersIO, Classmethod's owned media blog,
I've picked up 5 blogs that were especially well-read this year,
so together with the two guests joining us today, we'll
discuss those blogs, share impressions and thoughts—
that's what I'm hoping to do, so thank you for being here today.
B
Thank you.
C
Thank you for having us.
A
The first one is a blog about things to keep in mind when defining requirements,
with example requirements included, written by Nonpi.
B
The narrowness of the sidebar is something else
The full text is approximately 8,000 characters.
After converting and measuring the recorded audio, the audio duration was 19 minutes 1.696 seconds.
Running Transcription and Speaker Diarization with Amazon Transcribe
Place the audio to be transcribed in S3.
Specify LanguageCode as ja-JP and start the batch process.
For speaker diarization, specify ShowSpeakerLabels=true and MaxSpeakerLabels=3.
Extract the text and speaker labels from the processed JSON.
I'll cover only the setup steps necessary for the comparison.
The Python environment and dependencies are managed with uv.
Dependencies are fixed in pyproject.toml.
In this verification, Amazon Transcribe and faster-whisper run within the same project.
[project]
requires-python = "==3.12.*"
dependencies = [
"boto3==1.43.68",
"faster-whisper==1.2.1",
"pyannote==4.0.7",
]
Create the environment.
uv sync --all-groups --locked --python 3.12
From job start to JSON formatting, everything is combined into a single Python script (run_amazon_transcribe.py).
The following is an excerpt from part of it.
# Start the job
client = boto3.client("transcribe", region_name="ap-northeast-1")
client.start_transcription_job(
TranscriptionJobName=job_name,
LanguageCode="ja-JP",
MediaFormat="wav",
Media={"MediaFileUri": media_s3_uri},
Settings={
# Enable speaker diarization
"ShowSpeakerLabels": True,
# Since there are 3 speakers in this case, specify 3
"MaxSpeakerLabels": speaker_count,
},
)
# Wait for completion and retrieve JSON from TranscriptFileUri
response = client.get_transcription_job(TranscriptionJobName=job_name)
job = response["TranscriptionJob"]
status = job["TranscriptionJobStatus"]
if status == "COMPLETED":
uri = job["Transcript"]["TranscriptFileUri"]
# Process results.items one by one and format into speaker-labeled text
# Concatenate into the same segment until the speaker changes
for index, raw_item in enumerate(items):
content, confidence = _alternative(raw_item, index)
# Punctuation has no timestamps, so append it to the previous segment
if raw_item.get("type") == "punctuation":
if current_contents:
current_contents.append(content)
continue
speaker = raw_item.get("speaker_label")
if not isinstance(speaker, str):
# If the item has no speaker, look it up from speaker_labels.segments timestamps
speaker = speaker_by_times.get((str(start_raw), str(end_raw)))
# Finalize the segment when the speaker changes
if current_speaker is not None and speaker != current_speaker:
finish_segment()
current_contents.append(content)
Since characters are concatenated until the speaker changes to form a segment, utterances from the same speaker are combined into a single segment.
The job is invoked from a local terminal.
uv run --no-project --python 3.12 \
--with boto3==1.43.68 --with 'botocore[crt]' \
python run_amazon_transcribe.py \
--experiment experiment-full.json \
--media-s3-uri s3://<YOUR_BUCKET>/data/input-16khz-mono.wav \
--job-name roundtable-full-amazon-transcribe-20260811 \
--output results/transcribe-full/amazon-transcribe-full.json \
--raw-output results/transcribe-full/amazon-transcribe-full-raw.json \
--price-per-minute-usd 0.006 \
--poll-interval-seconds 5 \
--timeout-seconds 1200
The output is as follows.
Job status: COMPLETED
Processing time: 153.640 seconds
Number of speakers: 3
Processing time was measured as the total time from job start to speaker-labeled text formatting.
Speaker labels were assigned as 3 labels from spk_0 to spk_2.
This matches the specified MaxSpeakerLabels of 3.
Here is an excerpt from the beginning of the speaker-labeled text.
The transcription is formatted as follows.
[00:01.080-00:56.930] spk_0
Hello, this is the Classmethod YouTube channel. Today, since Classmethod is known as a blog company, on DevelopersIO, Classmethod's Wund media blog, the blogs that were especially well-read this year, I've picked up 5 of them,
(abbreviated)
[00:57.689-00:59.889] spk_1
The narrowness of the sidebar is amazing,
[00:59.930-01:11.919] spk_0
Right right right right right, you know Classmethod's blog has a navigation bar on the side where indexes are linked so you can jump to each section, but looking at this again, the number of rows is somehow incredible
[01:12.000-01:15.599] spk_2
Yeah. Originally. Wow.
Running Transcription and Speaker Diarization with faster-whisper and pyannote
With faster-whisper, we try the large-v3 and large-v3-turbo models.
Since the pyannote model (Community-1) responsible for speaker diarization uses CPU by default, we move the pipeline to GPU for GPU configurations.
Since we know there are 3 speakers, we specify num_speakers=3.
The Python environment and dependencies are managed with uv.
They share the same project as Amazon Transcribe, and the pyproject.toml dependencies are also common.
| Package | Version |
|---|---|
| faster-whisper | 1.2.1 |
| pyannote | 4.0.7 |
| torch | 2.13.0 |
From model loading through transcription, speaker diarization, and combining words with speaker segments, everything is combined into a single Python script.
The following is an excerpt from part of it.
# Load the model.
# Execute outside the measurement interval
whisper_model = WhisperModel(
configuration.model,
# cpu or cuda
device=configuration.device,
# int8 or float16
compute_type=configuration.compute_type or "default",
download_root=str(model_cache_dir / "faster-whisper"),
)
diarization_pipeline = Pipeline.from_pretrained(
"pyannote/speaker-diarization-community-1",
token=hf_token,
cache_dir=model_cache_dir / "pyannote",
)
if configuration.device == "cuda":
# Community-1 uses CPU by default, so move it to GPU
diarization_pipeline.to(torch.device("cuda"))
# Run transcription and speaker diarization.
# Only measure time for this interval
with ProcessingTimer() as timer:
raw_segments, info = whisper_model.transcribe(
str(audio_path),
language="ja",
beam_size=5,
# Get per-word timestamps to assign speakers
word_timestamps=True,
vad_filter=False,
)
words = extract_whisper_words(list(raw_segments))
# load_pcm_waveform reads PCM WAV and converts it to a waveform dictionary
# This is to avoid using TorchCodec's built-in decoder
diarization_audio = load_pcm_waveform(audio_path)
diarization_output = diarization_pipeline(
diarization_audio,
# Since we know the number of speakers, specify 3
num_speakers=speaker_count,
)
# Use exclusive_speaker_diarization.
# This allows overlapping speaker intervals to be handled exclusively
turns = extract_diarization_turns(
diarization_output.exclusive_speaker_diarization
)
segments = assign_speakers(words, turns)
def _speaker_for_word(word, turns):
"""Assign each word to the speaker interval with the maximum overlap time.
"""
overlaps = [
max(
0.0,
min(word.end_seconds, turn.end_seconds)
- max(word.start_seconds, turn.start_seconds),
)
for turn in turns
]
maximum_overlap = max(overlaps)
if maximum_overlap > 0:
return turns[overlaps.index(maximum_overlap)].speaker
# Words that don't overlap with any interval are assigned to the nearest interval by midpoint
midpoint = (word.start_seconds + word.end_seconds) / 2
return min(
turns,
key=lambda turn: min(
abs(midpoint - turn.start_seconds),
abs(midpoint - turn.end_seconds),
),
).speaker
Words are concatenated into segments until the assigned speaker changes.
This is the same concept as the Amazon Transcribe formatting.
Due to this rule, a single word at a speaker boundary may be absorbed into a different speaker's segment.
I'll list the execution commands and output for each configuration.
A Hugging Face token is required to use Community-1, so set it in an environment variable beforehand.
export HF_TOKEN="<YOUR_HF_TOKEN>"
Run large-v3 on CPU.
uv run python run_faster_whisper.py \
--experiment experiment-full.json \
--configuration-id fw-large-v3-cpu \
--output results/full/fw-large-v3-cpu-full.json \
--raw-output results/full/fw-large-v3-cpu-full-raw.json \
--hourly-price-usd 0.94376 \
--model-cache-dir models \
--instance-type c8i.4xlarge
The output is as follows.
Configuration: faster-whisper large-v3 CPU
Processing time: 1112.162 seconds
Detected language: ja
Number of speakers: 3
Run large-v3 on GPU.
In GPU configurations, since faster-whisper and pyannote call CUDA libraries, add the directory where those libraries are located to PATH and LD_LIBRARY_PATH.
export PATH="/usr/local/cuda-12.8/bin:$HOME/.local/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda-12.8/targets/x86_64-linux/lib:/usr/local/cuda-12.8/lib:${LD_LIBRARY_PATH:-}"
uv run python run_faster_whisper.py \
--experiment experiment-full.json \
--configuration-id fw-large-v3-gpu \
--output results/full/fw-large-v3-gpu-full.json \
--raw-output results/full/fw-large-v3-gpu-full-raw.json \
--hourly-price-usd 1.1672 \
--model-cache-dir models \
--instance-type g6.xlarge \
--gpu "NVIDIA L4"
The output is as follows.
Configuration: faster-whisper large-v3 GPU
Processing time: 147.239 seconds
Detected language: ja
Number of speakers: 3
Run large-v3-turbo on CPU.
uv run python run_faster_whisper.py \
--experiment experiment-full.json \
--configuration-id fw-large-v3-turbo-cpu \
--output results/full/fw-large-v3-turbo-cpu-full.json \
--raw-output results/full/fw-large-v3-turbo-cpu-full-raw.json \
--hourly-price-usd 0.94376 \
--model-cache-dir models \
--instance-type c8i.4xlarge
The output is as follows.
Configuration: faster-whisper large-v3-turbo CPU
Processing time: 654.488 seconds
Detected language: ja
Number of speakers: 3
Run large-v3-turbo on GPU.
uv run python run_faster_whisper.py \
--experiment experiment-full.json \
--configuration-id fw-large-v3-turbo-gpu \
--output results/full/fw-large-v3-turbo-gpu-full.json \
--raw-output results/full/fw-large-v3-turbo-gpu-full-raw.json \
--hourly-price-usd 1.1672 \
--model-cache-dir models \
--instance-type g6.xlarge \
--gpu "NVIDIA L4"
The output is as follows.
Configuration: faster-whisper large-v3-turbo GPU
Processing time: 67.584 seconds
Detected language: ja
Number of speakers: 3
The detected language was ja for all 4 configurations.
The number of speakers also matched at 3.
Here is an excerpt from the beginning of the speaker-labeled text for large-v3 CPU.
In the faster-whisper and pyannote.audio results, speaker labels like SPEAKER_00 were assigned by timestamp.
[00:01.220-00:57.920] SPEAKER_00
Hello Classmethod YouTube channel here today (abbreviated) quite a thorough output, the blog had quite a large amount of text too, side
[00:57.920-00:59.620] SPEAKER_02
bar's narrowness right right
[00:59.620-01:58.660] SPEAKER_00
right right Classmethod's blog has a navigation bar on the side (abbreviated) I think it's a blog for those who are in the position of building that system, by
[01:58.660-02:21.620] SPEAKER_01
myself when I saw this, I thought wow Nonpi's thinking is really (abbreviated)
Having Kiro Search for Error Candidates
I passed the reference text and the results from 5 configurations to Kiro.
The categories are used exactly as shown in the table above.
I had Kiro add timestamps and categories to each candidate, and list the corresponding sections from the reference text and output side by side.
Amazon Transcribe
The number of candidates raised for Amazon Transcribe is as follows.
| Category | Number of Candidates |
|---|---|
| Misrecognition | 31 |
| Omission | 9 |
| Addition | 2 |
| Proper Nouns | 16 |
| Numbers/English Words | 3 |
| Speaker Assignment Error | 28 |
Some categories have overlapping candidate counts.
For example, "Classmethod → Classzort" counts as 1 misrecognition and also as 1 proper noun error.
Therefore, simply adding up the counts across the 6 categories does not equal the total number of candidates.
Also, locations where person names or product names were rendered in katakana are not included as candidates.
This is because kanji or English characters cannot be determined from audio alone.
"Takayama-san" or "Githaabu" are not counted as errors.
Here are representative examples of proper noun candidates from Amazon Transcribe.
| Reference | Output | Timestamp |
|---|---|---|
| Owned media | Wund media | 00:01.080-00:56.930 |
| Classmethod | Classzort | 00:59.930-01:11.919 |
| NotebookLM | Notebook Eleven | 06:41.500-08:32.450 |
| Claude Code | Claude Court | 13:42.130-14:29.429 |
| Obsidian | Oburian | 15:37.140-16:19.119 |
| Omae-san | Omura-san | 17:11.609-17:34.369 |
NotebookLM was correctly output as "Notebook LM" only on the first occurrence.
From the second occurrence onward, all 3 instances were different strings.
Claude Code also varied.
There were locations where it correctly came out as "Claude Code," and locations where it became "Claude Court" or "Croud Code."
Here are representative examples of misrecognitions other than proper nouns.
| Reference | Output | Timestamp |
|---|---|---|
| Verbalized | Gamed | 01:58.110-02:18.990 |
| Availability | Diversity | 02:43.210-03:12.619 |
| Generative AI | Refined AI | 03:12.699-03:46.940 |
| Prompt engineering | Proto engineering | 05:13.183-05:38.360 |
| Going to check the logs | Going to the 5 people | 16:59.030-17:10.060 |
Here are representative examples of omissions.
| Reference | Output | Timestamp |
|---|---|---|
| Non-functional requirements | Functional requirements | 02:43.210-03:12.619 |
| Claude Code thorough explanation | Code thorough explanation | 11:52.155-13:23.005 |
| The most fundamental part | The best part | 14:40.969-14:47.320 |
There were also 2 candidates where entire utterances were not output at all.
These were "Do you use it for work?" around the 9-minute 51-second mark, and "Omae-san, how do you use it?" around the 16-minute 21-second mark.
No number errors were found.
"One-third," "5 items," "10 things," "2025," "May," and "June" all matched the reference.
The 28 speaker assignment candidates were mostly boundary shifts between segments.
At speaker transitions, a short utterance immediately before or after was absorbed into a different speaker's label.
For example:
[00:59.930-01:11.919] spk_0
(abbreviated) looking at this again somehow the number of rows is incredible
[01:12.000-01:15.599] spk_2
Yeah. Originally. Wow.
The "yeah" that follows spk_0's "incredible" went into spk_2.
In the reference, it is speech by the same speaker.
It also happened at the opening greeting.
Speaker B's "Thank you" and Speaker C's "Thank you for having us" were merged into Speaker A's segment.
faster-whisper + pyannote
The same audio was tested in 4 configurations with faster-whisper.
The extracted transcription candidates and speaker assignment error reference values are as follows.
| Category | large-v3 CPU | large-v3 GPU | large-v3-turbo CPU | large-v3-turbo GPU |
|---|---|---|---|---|
| Misrecognition | 35 | 31 | 41 | 32 |
| Omission | 3 | 4 | 3 | 4 |
| Addition | 1 | 3 | 5 | 2 |
| Proper Nouns | 10 | 7 | 11 | 11 |
| Numbers/English Words | 12 | 10 | 15 | 17 |
| Speaker Assignment Error | 40 | 37 | 36 | 34 |
Proper nouns and numbers/English words are partially counted in overlap with misrecognitions, omissions, and additions.
Examples Where Output Changed Due to Processor Difference
Even with the same model, the output sometimes differed depending on the processor.
The compute_type setting for arithmetic precision is set to int8 for CPU and float16 for GPU.
Since float16 is not optimized for CPU and is internally converted to float32 even when specified, I chose int8 for the CPU side, but this difference may be having an effect.
For this verification, I used these settings to get closer to actual use cases.
Below are the 2 configurations of large-v3 shown side by side.
| Reference | large-v3 CPU | large-v3 GPU |
|---|---|---|
| DevelopersIO | Developer The Io | Developer material |
| Prompt engineering | Pronto engineering | Prompt engineering |
| Put it in Cursor | Put it in a function | Put it in impressions |
| Icon | Hand of love | Affection |
| Good, I use it | It's said to be passed down | Good, I use it |
Only large-v3 GPU correctly output "Prompt engineering."
The CPU's int8 produced "Pronto."
Examples Where Text Not in the Audio Was Added
At the end of large-v3-turbo GPU, text not in the audio appeared.
Well then, thank you all very much, goodbye, thank you for watching
The end of the reference text is "Goodbye."
"Thank you for watching" was not spoken by anyone.
large-v3 GPU also produced a proper noun not in the audio.
Google-based documents can be linked to Kiehl's, right?
The reference is "Google-based documents can be linked, right?"
"Kiehl's" is the name of a real cosmetics brand.
Examples Where Speaker Labels Were Split Within a Word
In this verification, speaker labels were assigned by overlaying the speaker intervals detected by pyannote Community-1 onto the per-word timestamp information output by faster-whisper.
When word-level timestamps and speaker boundaries didn't align, a single word could be split across multiple speaker labels.
As an example, here are 2 excerpts from the large-v3 CPU output.
[10:36.160-10:36.480] SPEAKER_02 no-
[10:36.480-10:37.000] SPEAKER_00 vel it is
[10:37.000-10:37.240] SPEAKER_02 you know,
[10:37.240-11:16.760] SPEAKER_00 this. This is, you see. (abbreviated below)
In the reference, this is the section where Speaker B says "It's a novel, this." followed by Speaker A beginning to speak.
The single word "novel" was split into two parts and assigned to different speakers.
[05:39.700-05:47.360] SPEAKER_01 (abbreviated) please use Claude Code skills to
[05:47.360-05:48.220] SPEAKER_00 draw-
[05:48.220-05:50.080] SPEAKER_01 ing diagrams it assists with that
[05:50.080-05:51.540] SPEAKER_00 I saw that- also
[05:51.540-05:58.180] SPEAKER_01 there is (abbreviated below)
In the reference, this is the section where Speaker C says "it assists when drawing diagrams," with Speaker A interjecting "Oh, I saw that."
Only the first character of "drawing" was assigned to Speaker A in the middle of Speaker C's utterance, and the end of the immediately following Speaker A's utterance absorbed part of Speaker C's next line ("also").
Boundaries are not always at the beginning or end of an utterance.
Speakers can switch within a single word.
5. Compare the number of candidate errors and error patterns across configurations
We compare the number of cases by category across 5 configurations.
The values for the configuration with the best accuracy in each category are shown in bold.
| Category | Amazon Transcribe | large-v3 CPU | large-v3 GPU | large-v3-turbo CPU | large-v3-turbo GPU |
|---|---|---|---|---|---|
| Misrecognition | 31 | 35 | 31 | 41 | 32 |
| Omission | 9 | 3 | 4 | 3 | 4 |
| Addition | 2 | 1 | 3 | 5 | 2 |
| Proper nouns | 16 | 10 | 7 | 11 | 11 |
| Numbers / English words | 3 | 12 | 10 | 15 | 17 |
| Speaker assignment errors | 28 | 40 | 37 | 36 | 34 |
Proper nouns and numbers/English words are counted with partial overlap with misrecognition, omission, and addition.
Speaker assignment errors are reference values cross-checked against the ground truth text, audio, and output.
When totaling misrecognition, omission, and addition, Amazon Transcribe had 42 cases.
For faster-whisper: large-v3 CPU had 39 cases, large-v3 GPU had 38 cases, large-v3-turbo CPU had 49 cases, and large-v3-turbo GPU had 38 cases.
For the audio used this time, there was no significant difference in the total number of candidate errors.
However, there are trends in the types of errors.
Amazon Transcribe had 9 omissions, which was more than the 3–4 cases seen in faster-whisper.
Proper noun candidates were also higher for Amazon Transcribe at 16, compared to 7–11 for faster-whisper.
For numbers/English word candidates, Amazon Transcribe had 3 cases, while faster-whisper had 10–17.
For reference, here are the proper noun results listed by configuration.
| Correct | Amazon Transcribe | large-v3 CPU | large-v3 GPU | large-v3-turbo CPU | large-v3-turbo GPU |
|---|---|---|---|---|---|
| DevelopersIO | デベロッパーズIO | デベロッパー・ザ・イオー | デベロッパー材料 | デベロッパー内容 | デベロッパーズIo |
| のんピさん | のんぷさん | のんぴーさん | のんぴーさん | DOMPさん | ノンピさん |
| クラスメソッド側 | クラスの外側 | クラシマスット側 | クラシマスット側 | クラスマスター側 | クラスマスット側 |
| draw.io | ドロア | ドローIO | ドローIO | ドローア用 | ドローア用 |
| 非機能要件 | 機能要件 | 機能要件 | 機能要件 | 機能要件 | 機能要件 |
| 有料コンテンツ | 有料コンテ | 有料級 | 有料級 | 有料級 | 有料級 |
| Obsidian | オブリアン | Obsidian | Obsidian | オブシビア | オブシビアン |
| トーチさん | さん | 恒一さん | 康二さん | 小西さん | Omission |
"非機能要件" became "機能要件" across all five configurations.
The error of dropping "非" was the only one common to all configurations.
Correctness is determined by sound.
Whether the notation is in katakana or Latin characters does not matter.
"デベロッパーズIO" is counted as correct, and "デベロッパー材料" is treated as incorrect.
DevelopersIO resulted in a different string across all five configurations.
Two configurations — Amazon Transcribe and large-v3-turbo GPU — captured the sound correctly.
The remaining three configurations replaced it with different words.
draw.io showed a split trend between models.
The two large-v3 configurations produced "ドローIO."
The two large-v3-turbo configurations produced "ドローア用."
The same split occurred with "これの行が."
The two large-v3 configurations and Amazon Transcribe output "行."
The two large-v3-turbo configurations output "業."
Obsidian was correctly output in Latin characters only by the two large-v3 configurations.
There was a conversation mentioning the name of a blog author, but no configuration was able to identify the name correctly.
Amazon Transcribe dropped the family name and only retained "さん," while large-v3-turbo GPU did not output the family name at all.
The remaining three configurations each produced a different family name.
This part was confirmed by a human listening to the audio, and it was also a section that was slightly difficult to hear, so this is understandable.
NotebookLM had inconsistent notation within the same audio.
Some configurations changed notation between the first and second halves, with some degrading in the second half.
| Configuration | First half | Second half |
|---|---|---|
| Amazon Transcribe | ノートブックLM | ノートブックエM |
| large-v3 CPU | ノートブックLM | ノートブックエレメント |
| large-v3 GPU | ノートブックLM | notebook.lm |
| large-v3-turbo CPU | ノートブックLM | ノートブックLM |
| large-v3-turbo GPU | ノートブック11 | ノートブックエレム |
Only large-v3-turbo CPU maintained "ノートブックLM" throughout. It was the only one among the five configurations to do so.
Here is a summary of the number of correct answers for the 8 words mentioned so far.
| Configuration | Correct out of 8 | Words correct |
|---|---|---|
| Amazon Transcribe | 1 | DevelopersIO |
| large-v3 CPU | 3 | のんピさん、draw.io、Obsidian |
| large-v3 GPU | 3 | のんピさん、draw.io、Obsidian |
| large-v3-turbo CPU | 0 | ― |
| large-v3-turbo GPU | 2 | DevelopersIO、のんピさん |
These 8 words are ones where differences appeared between configurations.
This does not represent the overall results.
The following words were correctly recognized by all five configurations:
"AWS," "CDK," "GitHub," "MCP," "高山さん," "横田," "2025年," "3分の1"
The correspondence between speaker labels and the ground truth is as follows.
| Ground truth | Amazon Transcribe | faster-whisper (4 configurations) |
|---|---|---|
| Speaker A | spk_0 | SPEAKER_00 |
| Speaker B | spk_1 | SPEAKER_02 |
| Speaker C | spk_2 | SPEAKER_01 |
The mapping of the three speakers was consistent across all five configurations.
Comparing accuracy, processing time, and cost
Accuracy varies depending on what you prioritize.
For example, faster-whisper v3 achieved the best accuracy for proper nouns and omissions.
On the other hand, Transcribe showed high accuracy for speaker assignment and transcription of numbers/English words.
In terms of speed, faster-whisper large-v3-turbo was overwhelmingly faster.
Estimated cost
The estimated cost is calculated from the pricing table at the time of verification and the actual billable duration.
The audio length is 19 minutes 1.696 seconds.
The results are as follows.
| Configuration | Processing time | Estimated cost |
|---|---|---|
| Amazon Transcribe | 2 min 33.640 sec | $0.114200 |
| faster-whisper large-v3 CPU | 18 min 32.162 sec | $0.291779 |
| faster-whisper large-v3 GPU | 2 min 27.239 sec | $0.047985 |
| faster-whisper large-v3-turbo CPU | 10 min 54.488 sec | $0.171712 |
| faster-whisper large-v3-turbo GPU | 1 min 7.584 sec | $0.022047 |
The shortest processing time was large-v3-turbo GPU at 1 minute 7.584 seconds.
Amazon Transcribe came in second at 2 minutes 33.640 seconds.
The CPU-based large-v3 took 18 minutes 32.162 seconds, which is close to the actual playback duration of the audio.
The lowest estimated cost was large-v3-turbo GPU at $0.022047.
Amazon Transcribe came in at $0.114200, which is higher than large-v3 GPU at $0.047985.
The input audio is 1141.696 seconds.
Rounding up to the nearest second gives 1142 seconds.
Amazon Transcribe's billable unit is the input audio duration.
Processing time does not affect billing.
This differs from the billing basis of the four configurations running on EC2.
Conversely, for faster-whisper configurations, EC2 instances are provisioned in a somewhat fixed manner, so costs may vary depending on usage.
Each configuration was run once, and it cannot be definitively stated that the difference in processing times is reproducible.
Impressions
This time, we compared five configurations using a single audio file of approximately 19 minutes.
These are my personal impressions based on the results.
I had expected accuracy to be skewed toward one particular configuration, but it turned out that each configuration has its own strengths and weaknesses.
Also, regarding the processor, I think it is better to use a GPU if there are no constraints.
CPU processing takes longer, which ultimately leads to higher costs.
Since the accuracy was not significantly different from GPU, I don't think there is a particular reason to choose CPU.
Additionally, preparing the infrastructure and code to run faster-whisper took a considerable amount of time.
I worked alongside Kiro, but it ended up taking longer than expected.
Considering the effort of setting up and operating a transcription environment, I felt that Amazon Transcribe — as an AWS managed service — would be preferable if the cost is acceptable.
On the other hand, for cases where long audio is frequently transcribed, the cost of Amazon Transcribe cannot be ignored.
In such cases, it would be more cost-effective to build a mechanism that triggers EC2 instances or ECS on an event-driven basis.
Regarding accuracy, I felt there is room for improvement on proper noun errors by providing a dictionary.
Amazon Transcribe has custom vocabularies, and faster-whisper has initial_prompt.
Another approach would be to pass the transcribed data to an LLM for formatting and correction.
I would like to try this when I have time.
That concludes entry #18 of the "Summer Vacation Independent Research Relay": "Comparing Japanese Speech Transcription Accuracy Between Amazon Transcribe and faster-whisper"!
Next up will be Kitagawa-san's summer vacation independent research!
Stay tuned!!