fix a bug
This commit is contained in:
@@ -139,6 +139,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script src="/static/admin.js?v=admin-sentence-batch-v3" defer></script>
|
<script src="/static/admin.js?v=admin-sentence-batch-v5" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -389,13 +389,11 @@ async function handleSentenceDialogClose() {
|
|||||||
if (state.sentencePending) {
|
if (state.sentencePending) {
|
||||||
const persisted = await saveSentenceDraft({ processTimings: false });
|
const persisted = await saveSentenceDraft({ processTimings: false });
|
||||||
if (!persisted) {
|
if (!persisted) {
|
||||||
if (state.sentenceVideo && !elements.dialog.open) elements.dialog.showModal();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const processed = await saveSentenceDraft({ processTimings: true });
|
const processed = await saveSentenceDraft({ processTimings: true });
|
||||||
if (!processed) {
|
if (!processed) {
|
||||||
if (state.sentenceVideo && !elements.dialog.open) elements.dialog.showModal();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resetSentenceDraft();
|
resetSentenceDraft();
|
||||||
@@ -417,8 +415,17 @@ async function saveSentenceDraft({ processTimings = false } = {}) {
|
|||||||
index,
|
index,
|
||||||
originStartMs,
|
originStartMs,
|
||||||
originEndMs,
|
originEndMs,
|
||||||
|
sourceStartMs,
|
||||||
|
sourceEndMs,
|
||||||
...sentence
|
...sentence
|
||||||
}) => sentence),
|
}) => ({
|
||||||
|
...sentence,
|
||||||
|
...(sourceStartMs !== undefined && sourceEndMs !== undefined ? {
|
||||||
|
source_start_ms: sourceStartMs,
|
||||||
|
source_end_ms: sourceEndMs,
|
||||||
|
} : {}),
|
||||||
|
}),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
const saved = await api(
|
const saved = await api(
|
||||||
`/api/v1/admin/videos/${video.video_hash}/sentences/batch`,
|
`/api/v1/admin/videos/${video.video_hash}/sentences/batch`,
|
||||||
|
|||||||
@@ -936,7 +936,7 @@ def test_admin_batch_applies_merge_and_split_once(tmp_path, monkeypatch):
|
|||||||
assert all(not (item.zh_text or "").strip() for item in document.sentences)
|
assert all(not (item.zh_text or "").strip() for item in document.sentences)
|
||||||
|
|
||||||
|
|
||||||
def test_admin_batch_can_persist_provisional_split_without_processing(tmp_path):
|
def test_admin_batch_can_persist_provisional_split_without_processing(tmp_path, monkeypatch):
|
||||||
settings = replace(Settings.from_env(), data_dir=tmp_path / "data")
|
settings = replace(Settings.from_env(), data_dir=tmp_path / "data")
|
||||||
settings.ensure_directories()
|
settings.ensure_directories()
|
||||||
repository = VideoRepository(settings.database_path)
|
repository = VideoRepository(settings.database_path)
|
||||||
@@ -962,21 +962,43 @@ def test_admin_batch_can_persist_provisional_split_without_processing(tmp_path):
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
repository.save_sentence_translations(VIDEO_HASH, {1: "未变化。"})
|
repository.save_sentence_translations(VIDEO_HASH, {1: "未变化。"})
|
||||||
|
(settings.videos_dir / f"{VIDEO_HASH}.mp4").write_bytes(b"video")
|
||||||
|
from sentence_api.transcription import Transcript, TranscriptionSegment, WordTimestamp
|
||||||
|
|
||||||
calls = []
|
calls = []
|
||||||
|
|
||||||
class MustNotTranscribe:
|
class DeferredTranscriber:
|
||||||
available = True
|
available = True
|
||||||
|
allowed = False
|
||||||
|
|
||||||
def transcribe(self, audio_path, language=None):
|
def transcribe(self, audio_path, language=None):
|
||||||
|
assert self.allowed, "provisional save must not transcribe"
|
||||||
calls.append(audio_path)
|
calls.append(audio_path)
|
||||||
raise AssertionError("provisional save must not transcribe")
|
return Transcript(
|
||||||
|
text="First part second part",
|
||||||
|
segments=[
|
||||||
|
TranscriptionSegment(
|
||||||
|
start_seconds=0.0,
|
||||||
|
end_seconds=1.0,
|
||||||
|
text="First part second part",
|
||||||
|
words=[
|
||||||
|
WordTimestamp(0.0, 0.2, "First"),
|
||||||
|
WordTimestamp(0.2, 1.0, "part second part"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"sentence_api.processing.extract_audio_segment",
|
||||||
|
lambda media_path, output_path, *, start_ms, duration_ms: output_path.write_bytes(b"audio"),
|
||||||
|
)
|
||||||
client = TestClient(
|
client = TestClient(
|
||||||
create_app(
|
create_app(
|
||||||
BoundaryStore(tmp_path / "boundaries.json"),
|
BoundaryStore(tmp_path / "boundaries.json"),
|
||||||
settings=settings,
|
settings=settings,
|
||||||
repository=repository,
|
repository=repository,
|
||||||
transcriber=MustNotTranscribe(),
|
transcriber=DeferredTranscriber(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
response = client.put(
|
response = client.put(
|
||||||
@@ -1001,6 +1023,25 @@ def test_admin_batch_can_persist_provisional_split_without_processing(tmp_path):
|
|||||||
assert [item.text for item in document.sentences] == ["First part", "second part", "Unchanged."]
|
assert [item.text for item in document.sentences] == ["First part", "second part", "Unchanged."]
|
||||||
assert [item.zh_text for item in document.sentences] == [None, None, "未变化。"]
|
assert [item.zh_text for item in document.sentences] == [None, None, "未变化。"]
|
||||||
|
|
||||||
|
client.app.state.transcriber.allowed = True
|
||||||
|
processed = client.put(
|
||||||
|
f"/api/v1/admin/videos/{VIDEO_HASH}/sentences/batch",
|
||||||
|
json={
|
||||||
|
"process_timings": True,
|
||||||
|
"sentences": [
|
||||||
|
{"start_ms": 0, "end_ms": 2500, "text": "First part", "language": "en", "zh_text": None, "reference_speech_duration_ms": 2300, "source_start_ms": 0, "source_end_ms": 5000},
|
||||||
|
{"start_ms": 2500, "end_ms": 5000, "text": "second part", "language": "en", "zh_text": None, "reference_speech_duration_ms": 2300, "source_start_ms": 0, "source_end_ms": 5000},
|
||||||
|
{"start_ms": 5000, "end_ms": 12000, "text": "Unchanged.", "language": "en", "zh_text": "未变化。", "reference_speech_duration_ms": 6400},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert processed.status_code == 200, processed.text
|
||||||
|
processed_payload = processed.json()
|
||||||
|
assert [item["start_ms"] for item in processed_payload] == [0, 1000, 5000]
|
||||||
|
assert [item["end_ms"] for item in processed_payload] == [1000, 5000, 12000]
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
|
||||||
def test_admin_sentence_merge_does_not_start_subtitle_translation(tmp_path, monkeypatch):
|
def test_admin_sentence_merge_does_not_start_subtitle_translation(tmp_path, monkeypatch):
|
||||||
client = make_client(tmp_path)
|
client = make_client(tmp_path)
|
||||||
|
|||||||
Reference in New Issue
Block a user