fix: use native img tag for MJPEG live display
Live view now uses <img :src='streamUrl'> (browser-native MJPEG support, same as the working test HTML). The fetch-based multipart parser is kept only for recording frame capture. Also fixed multipart boundary parsing to correctly handle boundary values that already include leading dashes. - LiveView receives streamUrl string, passes it directly to <img> - useMjpegStream simplified to URL + state management - useRecorder manages its own fetch stream independently - RecorderControls shows recorder-specific errors
This commit is contained in:
+11
-13
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onUnmounted } from 'vue'
|
||||
import { config } from './config'
|
||||
import { useMjpegStream } from './composables/useMjpegStream'
|
||||
import { useRecorder } from './composables/useRecorder'
|
||||
import LiveView from './components/LiveView.vue'
|
||||
@@ -8,25 +7,22 @@ import RecorderControls from './components/RecorderControls.vue'
|
||||
import PlaybackPanel from './components/PlaybackPanel.vue'
|
||||
import ConfigPanel from './components/ConfigPanel.vue'
|
||||
|
||||
// ---- Stream ----
|
||||
const { isLive, error, frameUrl, start, stop, setOnFrame } = useMjpegStream()
|
||||
// ---- Stream (native <img> — no CORS issues) ----
|
||||
const { streamUrl, isLive, error, start, stop } = useMjpegStream()
|
||||
|
||||
// ---- Recorder ----
|
||||
// ---- Recorder (fetch-based frame capture) ----
|
||||
const {
|
||||
recorderState,
|
||||
elapsedMs,
|
||||
frameCount,
|
||||
onFrame,
|
||||
recorderError,
|
||||
startRecording,
|
||||
stopRecording,
|
||||
cancelRecording,
|
||||
formatElapsed,
|
||||
} = useRecorder()
|
||||
|
||||
// Wire recorder to stream frames
|
||||
setOnFrame(onFrame)
|
||||
|
||||
// ---- Playback panel ref (to refresh list after save) ----
|
||||
// ---- Playback panel ref ----
|
||||
const playbackRef = ref<InstanceType<typeof PlaybackPanel> | null>(null)
|
||||
|
||||
// ---- Active tab ----
|
||||
@@ -38,13 +34,13 @@ function handleConnect(url: string) {
|
||||
start(url)
|
||||
}
|
||||
|
||||
async function handleStartRecording() {
|
||||
startRecording()
|
||||
function handleStartRecording() {
|
||||
if (!streamUrl.value) return
|
||||
startRecording(streamUrl.value)
|
||||
}
|
||||
|
||||
async function handleStopRecording() {
|
||||
const recording = await stopRecording()
|
||||
// Refresh playback list
|
||||
playbackRef.value?.loadRecordings()
|
||||
if (recording) {
|
||||
activeTab.value = 'playback'
|
||||
@@ -59,6 +55,7 @@ const elapsedFormatted = computed(() => formatElapsed(elapsedMs.value))
|
||||
|
||||
onUnmounted(() => {
|
||||
stop()
|
||||
cancelRecording()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -94,12 +91,13 @@ onUnmounted(() => {
|
||||
|
||||
<!-- Tab: Live View -->
|
||||
<section v-show="activeTab === 'live'" class="tab-content">
|
||||
<LiveView :frame-url="frameUrl" :is-live="isLive" :error="error" />
|
||||
<LiveView :stream-url="streamUrl" :is-live="isLive" :error="error" />
|
||||
<RecorderControls
|
||||
:state="recorderState"
|
||||
:elapsed="elapsedFormatted"
|
||||
:frame-count="frameCount"
|
||||
:is-live="isLive"
|
||||
:error="recorderError"
|
||||
@start="handleStartRecording"
|
||||
@stop="handleStopRecording"
|
||||
@cancel="handleCancelRecording"
|
||||
|
||||
Reference in New Issue
Block a user