jeanma's picture
Omnilingual ASR transcription demo
ae238b3 verified
import React, { useState } from 'react';
import { formatTime } from '../utils/subtitleUtils';
import { useTranscriptionStore } from '../stores/transcriptionStore';
import { InformationCircleIcon } from '@heroicons/react/24/outline';
const FullTranscription: React.FC = () => {
const [showInfoTooltip, setShowInfoTooltip] = useState(false);
const [showExpandedChunks, setShowExpandedChunks] = useState(false);
const { transcription, selectedLanguage } = useTranscriptionStore();
const renderInfoTooltip = () => {
if (!transcription) return null;
const chunks = transcription.chunks || [];
const maxVisibleChunks = 3;
const hasMoreChunks = chunks.length > maxVisibleChunks;
const visibleChunks = showExpandedChunks ? chunks : chunks.slice(0, maxVisibleChunks);
// Calculate better positioning to avoid edge cuts
const tooltipStyle: React.CSSProperties = {
position: 'fixed',
left: '50%',
top: '50%',
transform: 'translate(-50%, -50%)',
maxHeight: '80vh', // Prevent tooltip from being taller than viewport
overflowY: 'auto' as const
};
return (
<div
className="z-50 p-3 bg-gray-900 text-white text-xs rounded-lg shadow-xl border border-gray-600 min-w-64 max-w-96"
style={tooltipStyle}>
<div className="font-semibold mb-2 text-blue-300">Transcription Details</div>
<div className="space-y-1">
<div className="flex justify-between">
<span className="text-gray-300">Model:</span>
<span>{transcription.model}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Language:</span>
<span className="font-mono">
{selectedLanguage || 'auto-detect'}
</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Segments:</span>
<span>{transcription.num_segments}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Duration:</span>
<span>{formatTime(transcription.total_duration)}</span>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Device:</span>
<span className="font-mono">{transcription.device}</span>
</div>
{/* Long-form specific info */}
{transcription.num_chunks && (
<>
<div className="border-t border-gray-600 pt-1 mt-1">
<div className="text-xs text-blue-300 font-semibold mb-1">Long-form Processing</div>
</div>
<div className="flex justify-between">
<span className="text-gray-300">Chunks:</span>
<span>{transcription.num_chunks}</span>
</div>
</>
)}
</div>
{/* Improved Chunk details */}
{chunks.length > 0 && (
<div className="mt-2">
<div className="flex items-center justify-between mb-1">
<div className="text-xs text-blue-300 font-semibold">Chunk Details</div>
{hasMoreChunks && (
<button
onClick={() => setShowExpandedChunks(!showExpandedChunks)}
className="text-xs text-blue-400 hover:text-blue-300 underline transition-colors"
>
{showExpandedChunks ? 'Show Less' : `Show All (${chunks.length})`}
</button>
)}
</div>
<div className="space-y-1 max-h-48 overflow-y-auto">
{visibleChunks.map((chunk, index) => (
<div key={index} className="text-xs bg-gray-700 p-2 rounded border border-gray-600">
<div className="flex justify-between items-start">
<div className="font-medium text-gray-200">
Chunk #{index + 1}
</div>
<div className="text-gray-400 text-xs">
{chunk.duration.toFixed(1)}s
</div>
</div>
<div className="text-gray-300 font-mono mt-1">
{formatTime(chunk.start_time)} → {formatTime(chunk.end_time)}
</div>
</div>
))}
{hasMoreChunks && !showExpandedChunks && (
<div className="text-center py-1">
<button
onClick={() => setShowExpandedChunks(true)}
className="text-xs text-blue-400 hover:text-blue-300 underline transition-colors"
>
+{chunks.length - maxVisibleChunks} more chunks...
</button>
</div>
)}
</div>
</div>
)}
</div>
);
};
if (!transcription) return null;
return (
<div className="p-4 bg-gray-800 border-t border-gray-700">
<div className="flex items-center gap-2 mb-3">
<h3 className="text-sm font-semibold text-white">Full Transcription</h3>
{/* Info tooltip */}
<div className="relative">
<InformationCircleIcon
className="w-4 h-4 text-gray-400 hover:text-gray-200 cursor-help transition-colors"
onMouseEnter={() => setShowInfoTooltip(true)}
onMouseLeave={() => setShowInfoTooltip(false)}
/>
{showInfoTooltip && renderInfoTooltip()}
</div>
</div>
<div className="text-sm max-h-32 overflow-y-auto text-gray-300 font-mono bg-gray-900 p-3 rounded border border-gray-600">
{transcription.transcription}
</div>
</div>
);
};
export default FullTranscription;