Очень странная проблема у меня есть в iOS, когда общая сеть в качестве приложения (PWA) на домашний экран.
всякий раз, когда я использую его через браузер Safari на iPhone, он работает на 100% каждый раз. Однако, когда я помещаю его в качестве приложения на главном экране, в первый раз я открываю его, он работает нормально, когда я закрываю его и снова открываю, он просто не начинает записывать. Я должен перезагрузить телефон, чтобы он работал. Так что это работает один раз, я думаю, каким -то образом он не закончится потоком или что -то в этом роде, но в коде я попробовал все возможные способы закрыть и очистить трек. Пробовал GPT, Claude, Gemini Solutions. Ничего не сработало, это просто работает 1 раз как PWA. Моя последняя надежда - кто -то еще столкнулся с этой проблемой и может попытаться помочь мне?
p.s. Android работает нормально. < /P>
import { ref, computed } from 'vue'
import axios from 'axios'
const captureState = ref('idle') // idle | recording | analyzing
const showReviewModal = ref(false)
const transcript = ref('')
const showTranscript = ref(false)
const tasks = ref([]) // {id, title, selected}
const recordingId = ref(null)
const errorMessage = ref('')
const isSending = ref(false)
const statusText = computed(() => {
switch (captureState.value) {
case 'recording': return 'Recording... Tap to stop'
case 'analyzing': return 'Analyzing your thoughts...'
default: return 'Tap to start recording'
}
})
const selectedCount = computed(() => tasks.value.filter(t => t.selected).length)
let mediaStream = null
let mediaRecorder = null
let chunks = []
async function handleCapture () {
if (captureState.value === 'idle') {
await startRecording()
} else if (captureState.value === 'recording') {
await stopRecording()
}
}
async function startRecording () {
errorMessage.value = ''
try {
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
throw new Error('Audio recording requires HTTPS')
}
if (!navigator.mediaDevices?.getUserMedia) {
throw new Error('Audio recording not supported in this browser')
}
mediaStream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true
},
video: false
})
const mimeType = getSupportedAudioType()
mediaRecorder = new MediaRecorder(mediaStream, { mimeType })
chunks = []
mediaRecorder.ondataavailable = (e) => {
if (e.data && e.data.size > 0) chunks.push(e.data)
}
mediaRecorder.onstop = async () => {
try {
const blob = new Blob(chunks, { type: mimeType })
if (!blob || blob.size === 0) throw new Error('No audio data recorded')
captureState.value = 'analyzing'
await sendRecording(blob)
} catch (err) {
errorMessage.value = err?.message || String(err)
captureState.value = 'idle'
} finally {
cleanupMedia()
}
}
mediaRecorder.start()
captureState.value = 'recording'
} catch (err) {
errorMessage.value = err?.message || String(err)
cleanupMedia()
captureState.value = 'idle'
}
}
async function stopRecording () {
try {
if (mediaRecorder && mediaRecorder.state !== 'inactive') {
mediaRecorder.stop()
} else {
cleanupMedia()
captureState.value = 'idle'
}
} catch (err) {
errorMessage.value = 'Error stopping recording: ' + (err?.message || String(err))
cleanupMedia()
captureState.value = 'idle'
}
}
function cleanupMedia () {
try {
mediaRecorder?.stop?.()
} catch {}
mediaRecorder = null
chunks = []
if (mediaStream) {
try {
mediaStream.getTracks().forEach(t => {
try { t.stop() } catch {}
})
} catch {}
}
mediaStream = null
}
function getSupportedAudioType () {
const types = [
'audio/webm;codecs=opus',
'audio/webm',
'audio/ogg;codecs=opus',
'audio/ogg',
'audio/mp4',
'audio/mpeg'
]
for (const t of types) {
if (MediaRecorder.isTypeSupported?.(t)) return t
}
return ''
}
async function sendRecording (blob) {
if (!blob) return
isSending.value = true
try {
const fileName = pickFileNameFromType(blob.type)
const formData = new FormData()
const file = new File([blob], fileName, { type: blob.type || 'application/octet-stream' })
formData.append('audio', file)
const res = await axios.post('/recordings', formData)
recordingId.value = res.data.recording_id
transcript.value = res.data.transcript
showTranscript.value = false
tasks.value = (res.data.tasks || []).map(t => ({ ...t, selected: true }))
showReviewModal.value = true
} catch (e) {
errorMessage.value = e?.response?.data?.message || e?.message || 'Upload failed'
} finally {
isSending.value = false
captureState.value = 'idle'
}
}
function pickFileNameFromType (type) {
if (type.includes('webm')) return 'recording.webm'
if (type.includes('ogg')) return 'recording.ogg'
if (type.includes('mp4') || type.includes('mpeg')) return 'recording.m4a'
return 'recording.bin'
}
async function addTasks () {
if (!recordingId.value) return
isSending.value = true
try {
await axios.post(`/recordings/${recordingId.value}/tasks`, { tasks: tasks.value })
window.location.href = '/tasks'
} catch (e) {
errorMessage.value = e.response?.data?.message || e.message
} finally {
isSending.value = false
}
}
function resetRecording () {
showReviewModal.value = false
transcript.value = ''
tasks.value = []
recordingId.value = null
errorMessage.value = ''
showTranscript.value = false
}
document.addEventListener('visibilitychange', () => {
if (document.hidden && captureState.value === 'recording') {
stopRecording()
}
})
window.addEventListener('pagehide', () => {
if (captureState.value === 'recording') {
stopRecording()
} else {
cleanupMedia()
}
})
Подробнее здесь: https://stackoverflow.com/questions/797 ... all-tracks
MediareCorder застрял на iOS в качестве приложения PWA, как очистить все треки? ⇐ Javascript
Форум по Javascript
1756000610
Anonymous
Очень странная проблема у меня есть в iOS, когда общая сеть в качестве приложения (PWA) на домашний экран.
всякий раз, когда я использую его через браузер Safari на iPhone, он работает на 100% каждый раз. Однако, когда я помещаю его в качестве приложения на главном экране, в первый раз я открываю его, он работает нормально, когда я закрываю его и снова открываю, он просто не начинает записывать. Я должен перезагрузить телефон, чтобы он работал. Так что это работает один раз, я думаю, каким -то образом он не закончится потоком или что -то в этом роде, но в коде я попробовал все возможные способы закрыть и очистить трек. Пробовал GPT, Claude, Gemini Solutions. Ничего не сработало, это просто работает 1 раз как PWA. Моя последняя надежда - кто -то еще столкнулся с этой проблемой и может попытаться помочь мне?
p.s. Android работает нормально. < /P>
import { ref, computed } from 'vue'
import axios from 'axios'
const captureState = ref('idle') // idle | recording | analyzing
const showReviewModal = ref(false)
const transcript = ref('')
const showTranscript = ref(false)
const tasks = ref([]) // {id, title, selected}
const recordingId = ref(null)
const errorMessage = ref('')
const isSending = ref(false)
const statusText = computed(() => {
switch (captureState.value) {
case 'recording': return 'Recording... Tap to stop'
case 'analyzing': return 'Analyzing your thoughts...'
default: return 'Tap to start recording'
}
})
const selectedCount = computed(() => tasks.value.filter(t => t.selected).length)
let mediaStream = null
let mediaRecorder = null
let chunks = []
async function handleCapture () {
if (captureState.value === 'idle') {
await startRecording()
} else if (captureState.value === 'recording') {
await stopRecording()
}
}
async function startRecording () {
errorMessage.value = ''
try {
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
throw new Error('Audio recording requires HTTPS')
}
if (!navigator.mediaDevices?.getUserMedia) {
throw new Error('Audio recording not supported in this browser')
}
mediaStream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true
},
video: false
})
const mimeType = getSupportedAudioType()
mediaRecorder = new MediaRecorder(mediaStream, { mimeType })
chunks = []
mediaRecorder.ondataavailable = (e) => {
if (e.data && e.data.size > 0) chunks.push(e.data)
}
mediaRecorder.onstop = async () => {
try {
const blob = new Blob(chunks, { type: mimeType })
if (!blob || blob.size === 0) throw new Error('No audio data recorded')
captureState.value = 'analyzing'
await sendRecording(blob)
} catch (err) {
errorMessage.value = err?.message || String(err)
captureState.value = 'idle'
} finally {
cleanupMedia()
}
}
mediaRecorder.start()
captureState.value = 'recording'
} catch (err) {
errorMessage.value = err?.message || String(err)
cleanupMedia()
captureState.value = 'idle'
}
}
async function stopRecording () {
try {
if (mediaRecorder && mediaRecorder.state !== 'inactive') {
mediaRecorder.stop()
} else {
cleanupMedia()
captureState.value = 'idle'
}
} catch (err) {
errorMessage.value = 'Error stopping recording: ' + (err?.message || String(err))
cleanupMedia()
captureState.value = 'idle'
}
}
function cleanupMedia () {
try {
mediaRecorder?.stop?.()
} catch {}
mediaRecorder = null
chunks = []
if (mediaStream) {
try {
mediaStream.getTracks().forEach(t => {
try { t.stop() } catch {}
})
} catch {}
}
mediaStream = null
}
function getSupportedAudioType () {
const types = [
'audio/webm;codecs=opus',
'audio/webm',
'audio/ogg;codecs=opus',
'audio/ogg',
'audio/mp4',
'audio/mpeg'
]
for (const t of types) {
if (MediaRecorder.isTypeSupported?.(t)) return t
}
return ''
}
async function sendRecording (blob) {
if (!blob) return
isSending.value = true
try {
const fileName = pickFileNameFromType(blob.type)
const formData = new FormData()
const file = new File([blob], fileName, { type: blob.type || 'application/octet-stream' })
formData.append('audio', file)
const res = await axios.post('/recordings', formData)
recordingId.value = res.data.recording_id
transcript.value = res.data.transcript
showTranscript.value = false
tasks.value = (res.data.tasks || []).map(t => ({ ...t, selected: true }))
showReviewModal.value = true
} catch (e) {
errorMessage.value = e?.response?.data?.message || e?.message || 'Upload failed'
} finally {
isSending.value = false
captureState.value = 'idle'
}
}
function pickFileNameFromType (type) {
if (type.includes('webm')) return 'recording.webm'
if (type.includes('ogg')) return 'recording.ogg'
if (type.includes('mp4') || type.includes('mpeg')) return 'recording.m4a'
return 'recording.bin'
}
async function addTasks () {
if (!recordingId.value) return
isSending.value = true
try {
await axios.post(`/recordings/${recordingId.value}/tasks`, { tasks: tasks.value })
window.location.href = '/tasks'
} catch (e) {
errorMessage.value = e.response?.data?.message || e.message
} finally {
isSending.value = false
}
}
function resetRecording () {
showReviewModal.value = false
transcript.value = ''
tasks.value = []
recordingId.value = null
errorMessage.value = ''
showTranscript.value = false
}
document.addEventListener('visibilitychange', () => {
if (document.hidden && captureState.value === 'recording') {
stopRecording()
}
})
window.addEventListener('pagehide', () => {
if (captureState.value === 'recording') {
stopRecording()
} else {
cleanupMedia()
}
})
Подробнее здесь: [url]https://stackoverflow.com/questions/79744644/mediarecorder-stucks-on-ios-as-pwa-app-how-to-clean-all-tracks[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия