feat: add additional timestamps in call transcript optionally

This commit is contained in:
Sabiha Khan 2026-07-06 09:12:50 +05:30
parent b3e09be9b0
commit 44053d0a6d
12 changed files with 317 additions and 15 deletions

View file

@ -1,10 +1,12 @@
from api.services.pipecat.realtime_feedback_events import (
build_bot_text_event,
build_function_call_end_event,
build_user_transcription_event,
build_node_transition_event,
realtime_feedback_event_sort_key,
stamp_realtime_feedback_event,
)
from api.utils.transcript import generate_transcript_text
def test_build_function_call_end_event_serializes_results():
@ -51,3 +53,38 @@ def test_stamp_and_sort_realtime_feedback_events():
assert events == [bot_text, node_transition]
assert node_transition["node_id"] == "node-1"
assert node_transition["node_name"] == "Greeting"
def test_transcript_can_include_end_timestamps_without_changing_default_format():
events = [
stamp_realtime_feedback_event(
build_bot_text_event(
text="Can you confirm your date of birth?",
timestamp="2026-01-01T00:00:01+00:00",
end_timestamp="2026-01-01T00:00:04+00:00",
),
timestamp="2026-01-01T00:00:05+00:00",
turn=0,
),
stamp_realtime_feedback_event(
build_user_transcription_event(
text="January fifth",
final=True,
timestamp="2026-01-01T00:00:06+00:00",
end_timestamp="2026-01-01T00:00:08+00:00",
),
timestamp="2026-01-01T00:00:09+00:00",
turn=1,
),
]
assert generate_transcript_text(events) == (
"[2026-01-01T00:00:01+00:00] assistant: Can you confirm your date of birth?\n"
"[2026-01-01T00:00:06+00:00] user: January fifth\n"
)
assert generate_transcript_text(events, include_end_timestamps=True) == (
"[2026-01-01T00:00:01+00:00 -> 2026-01-01T00:00:04+00:00] "
"assistant: Can you confirm your date of birth?\n"
"[2026-01-01T00:00:06+00:00 -> 2026-01-01T00:00:08+00:00] "
"user: January fifth\n"
)

View file

@ -1,7 +1,14 @@
from types import SimpleNamespace
import pytest
from pipecat.frames.frames import TranscriptionFrame, TTSTextFrame
from pipecat.frames.frames import (
BotStartedSpeakingFrame,
BotStoppedSpeakingFrame,
TranscriptionFrame,
TTSTextFrame,
UserStartedSpeakingFrame,
UserStoppedSpeakingFrame,
)
from pipecat.observers.base_observer import FramePushed
from pipecat.processors.frame_processor import FrameDirection
from pipecat.transports.base_output import BaseOutputTransport
@ -144,3 +151,55 @@ async def test_turn_log_handlers_persist_user_message_added_events():
"timestamp": "2026-01-01T00:00:00+00:00",
}
assert events[0]["turn"] == 1
@pytest.mark.asyncio
async def test_observer_attaches_backend_speaking_intervals_to_logged_transcript_events():
async def ws_sender(_message):
pass
logs_buffer = InMemoryLogsBuffer(workflow_run_id=123)
observer = RealtimeFeedbackObserver(ws_sender=ws_sender, logs_buffer=logs_buffer)
user_aggregator = _FakeAggregator()
assistant_aggregator = _FakeAggregator()
register_turn_log_handlers(logs_buffer, user_aggregator, assistant_aggregator)
await observer.on_push_frame(
_frame_pushed(UserStartedSpeakingFrame(), FrameDirection.DOWNSTREAM)
)
await observer.on_push_frame(
_frame_pushed(UserStoppedSpeakingFrame(), FrameDirection.DOWNSTREAM)
)
await user_aggregator.handlers["on_user_turn_message_added"](
user_aggregator,
SimpleNamespace(
content="January fifth",
timestamp="aggregator-user-start",
),
)
await observer.on_push_frame(
_frame_pushed(BotStartedSpeakingFrame(), FrameDirection.DOWNSTREAM)
)
await assistant_aggregator.handlers["on_assistant_turn_stopped"](
assistant_aggregator,
SimpleNamespace(
content="Thank you",
timestamp="aggregator-bot-start",
),
)
await observer.on_push_frame(
_frame_pushed(BotStoppedSpeakingFrame(), FrameDirection.DOWNSTREAM)
)
user_event, bot_event = [
event
for event in logs_buffer.get_events()
if event["type"] in {"rtf-user-transcription", "rtf-bot-text"}
]
assert user_event["payload"]["timestamp"] != "aggregator-user-start"
assert user_event["payload"]["end_timestamp"]
assert bot_event["payload"]["timestamp"] != "aggregator-bot-start"
assert bot_event["payload"]["end_timestamp"]