JS. Запись потокового звука в Chrome и его воспроизведение в Safari
Есть скрипт для запуска потоковой записи аудио в браузере и последующей ее загрузке на сервер
navigator.mediaDevices.getUserMedia({audio: true})
.then(stream => {
const mediaRecorder = new MediaRecorder(stream)
let audioChunks = []
mediaRecorder.addEventListener('dataavailable', e => audioChunks.push(e.data))
document.addEventListener('click', e => {
// начало записи
if (e.target.closest('.dialogs-footer__area-voice')) {
area.classList.add('_rec')
textarea.setAttribute('disabled', '')
start()
mediaRecorder.start()
// конец записи
} else if (e.target.closest('.dialogs-footer__area-stop')) {
area.classList.remove('_rec')
textarea.removeAttribute('disabled')
clearInterval(interval)
min = sec = ms = 0
mediaRecorder.stop()
}
})
mediaRecorder.addEventListener("stop", async () => {
const formData = new FormData(),
audioBlob = new Blob(audioChunks, {
type: 'audio/mp3'
})
let axiosResponse;
formData.append('action', 'rec')
formData.append('voice', audioBlob)
await axios.post(URL, formData)
.then(response => {
console.log(response.data);
axiosResponse = response.data
})
const todayChat = document.querySelector('.dialogs-body__day._today'),
newMessage = document.createElement('div')
newMessage.className = 'dialogs-body__manager'
newMessage.innerHTML = `
<div class="dialogs-body__manager-audio audio">
<div class="audio__info">
<p class="audio__info-name">${axiosResponse.name}</p>
<p class="audio__info-date">${axiosResponse.time}</p>
</div>
<div class="audio__item">
<div class="audio__item-inner">
<audio class="audio__item-audio" controls>
<source src="/uploads/${axiosResponse.title}">
</audio>
<div class="audio__item-button"></div>
<div class="audio__item-progress"></div>
<div class="audio__item-time"></div>
</div>
</div>
</div>`
if (todayChat) {
todayChat.append(newMessage)
scrollDown('.dialogs-body__chat')
} else {
createtodayChat().append(newMessage)
scrollDown('.dialogs-body__chat')
}
initAudio(newMessage)
audioChunks = []
})
})
function initAudio(audioItem) {
let finishItem = audioItem.querySelector('.audio__item-time'),
audioFile = audioItem.querySelector('.audio__item-audio'),
slider = audioItem.querySelector('.audio__item-progress')
if (audioFile.duration) {
foo()
} else {
audioFile.addEventListener('loadedmetadata', foo)
}
function foo() {
if (audioFile.duration === Infinity) {
audioFile.currentTime = 1e101;
audioFile.ontimeupdate = function() {
this.ontimeupdate = () => {
return;
}
audioFile.currentTime = 0;
createSlider()
}
return
}
createSlider()
function createSlider() {
noUiSlider.create(slider, {
start: 0,
connect: 'lower',
range: {
'min': 0,
'max': audioFile.duration
}
})
audioItem.querySelector('.noUi-origin').setAttribute('disabled', true)
finishItem.innerText = String.prototype.toMMSS(audioFile.duration.toString())
}
}
}
в php этот файл принимается, переносится в нужное место и возвращается его имя
if ($_POST['action'] === 'rec') {
$path = $_SERVER['DOCUMENT_ROOT'] . '/uploads/';
$type_file = explode('/', $_FILES['voice']['type'])[1];
if (move_uploaded_file($_FILES['voice']['tmp_name'], $path . date('YmdHis') . '.' . $type_file)) {
// Далее можно сохранить название файла в БД и т.п.
$response = [
'name' => $arr['name'],
'time' => $arr['time'],
'title' => date('YmdHis') . '.' . $type_file
];
echo json_encode($response);
}
}
В инициализации, как видно, я проверяю длину файла на бесконечность, т.к. из-за бага Chrome именно такая длина аудио возвращается. Вопрос следующий: все везде работает прекрасно, но записанные в Chrome аудио не работают в Safari. Проблема, насколько я понял, давняя. Есть ли возможность как то решить ее?
Решено.