feat: Mark failed recordings with .m4a.failed
Add a new `failed` field to `RecordingView` and corresponding logic in the worker. When FFmpeg remuxing or Whisper transcription fails, the worker now renames the original `.m4a` file to `.m4a.failed`. This prevents the recovery scan from reprocessing these files and signals to the UI that transcription failed. The UI displays a message indicating failure and suggests renaming the file back to `.m4a` to retry. A new integration test `worker_renames_audio_to_failed_on_whisper_error` is included to verify this behavior.
This commit is contained in:
@@ -15,6 +15,8 @@ body { font-family: sans-serif; max-width: 900px; margin: 2em auto; padding: 0 1
|
||||
.recording-head span { font-family: monospace; font-size: 0.9em; min-width: 20em; }
|
||||
.transcript { margin: 0.5em 0 0 1em; padding: 0.5em; background: #f6f6f6; border-radius: 4px; white-space: pre-wrap; font-family: serif; }
|
||||
.pending { margin: 0.5em 0 0 1em; color: #888; font-style: italic; }
|
||||
.failed { margin: 0.5em 0 0 1em; color: #b00; font-weight: bold; }
|
||||
.recording.failed-row { background: #fff7f7; border-left: 3px solid #e24a4a; padding-left: 0.5em; }
|
||||
.oneliner { font-size: 1em; color: #333; margin: 0 0 0.3em 0; }
|
||||
</style>
|
||||
</head>
|
||||
@@ -33,19 +35,23 @@ body { font-family: sans-serif; max-width: 900px; margin: 2em auto; padding: 0 1
|
||||
{% endmatch %}
|
||||
<small>{{ case.case_id }}</small>
|
||||
{% for rec in case.recordings %}
|
||||
<div class="recording">
|
||||
<div class="recording{% if rec.failed %} failed-row{% endif %}">
|
||||
<div class="recording-head">
|
||||
<span>{{ rec.filename }}</span>
|
||||
<audio controls preload="none">
|
||||
<source src="/web/audio/{{ case.user_slug }}/{{ case.case_id }}/{{ rec.filename }}" type="audio/mp4">
|
||||
</audio>
|
||||
</div>
|
||||
{% if rec.failed %}
|
||||
<div class="failed">Transcription failed — rename away the .failed suffix to retry.</div>
|
||||
{% else %}
|
||||
{% match rec.transcript %}
|
||||
{% when Some with (t) %}
|
||||
<div class="transcript">{{ t }}</div>
|
||||
{% when None %}
|
||||
<div class="pending">Transcription pending…</div>
|
||||
{% endmatch %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user