Здравствуйте, у меня есть небольшое веб-приложение, в котором клиент может оставить отзыв о ресторане. Есть возможность записать голосовую заметку. Когда я записываю голос в Chrome, Firefox, Opera. На Mac или Windows все работает, и я слышу голос, отправленный боту Telegram. Но запись в Safari voice воспроизводится без голоса. В IOS та же проблема в браузерах Chrome и Safari.
Вот мой код:
const mic_btn = document.querySelector("#record__button");
const playback = document.querySelector(".playback");
const voiceRemove = document.getElementById("removeVoive");
const voiceBody = document.querySelector(".record__body");
const openRecorder = document.querySelector(".record__open-recorder");
let counter = document.getElementById("counter");
openRecorder.addEventListener("click", () => {
voiceBody.classList.add("_active");
setupAudio();
});
mic_btn.addEventListener("click", toggleMic);
voiceRemove.addEventListener("click", () => {
voiceRemove.classList.remove("_active");
playback.classList.remove("_active");
playback.src = "";
counter.innerHTML = "1:00";
});
let can_record = false;
let is_recording = false;
let recorder = null;
let chuncs = [];
let voice = [];
function setupAudio() {
console.info("Sterted");
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices
.getUserMedia({
audio: true,
})
.then(setupStream)
.catch((err) => {
console.error(err);
});
}
}
function setupStream(stream) {
recorder = new MediaRecorder(stream);
recorder.ondataavailable = (e) => {
chuncs.push(e.data);
voice.push(e.data);
};
recorder.onstop = () => {
const blob = new Blob(chuncs, { type: "audio/wav" });
chuncs = [];
const audioUrl = window.URL.createObjectURL(blob);
playback.src = audioUrl;
playback.classList.add("_active");
voiceRemove.classList.add("_active");
};
can_record = true;
}
let count;
let recordingInterval;
function toggleMic() {
if (!can_record) return;
is_recording = !is_recording;
if (is_recording) {
recorder.start();
mic_btn.classList.add("is-recording");
count = true;
if (count) {
recordingInterval = setInterval(() => {
recorder.stop();
mic_btn.classList.remove("is-recording");
count = false;
}, 60000);
}
tick();
} else {
recorder.stop();
mic_btn.classList.remove("is-recording");
count = false;
clearInterval(recordingInterval);
}
}
// Timer
let seconds = 60;
// Count down timer function
function tick() {
if (count) {
seconds--;
counter.innerHTML = "0:" + (seconds < 10 ? "0" : "") + String(seconds);
if (seconds > 0) {
setTimeout(tick, 1000);
}
} else {
seconds = 60;
}
}
const form = document.getElementById('form-main');
form.addEventListener('submit', formSend);
async function formSend(e) {
e.preventDefault();
const audioBlob = new Blob(voice, { type: 'audio/mp4; codecs=opus' });
voice = [];
let error = formValidate(form);
let formData = new FormData(form);
formData.append('image', formImage.files[0]);
formData.append("audio_file", audioBlob, "voice.mp4");
if (error === 0) {
form.classList.add('_sending');
let response = await fetch('/save', {
method: 'POST',
cache: 'no-cache',
body: formData,
});
if (response.ok) {
let result = await response.json();
form.reset();
form.classList.remove('_sending');
} else {
console.info('Error');
form.classList.remove('_sending');
}
} else {
console.error('error');
}
}
И PHP:
if (isset($_FILES["audio_file"])) {
$voice = $_FILES["audio_file"];
$voice_tmp = $voice["tmp_name"];
$voice_name = $voice["name"];
// File info
$temp_voice = explode(".", $voice_name);
$new_voice_name = round(microtime(true)) . '.' . end($temp_voice);
}
// Save voice and sending to a telegram
if (!empty($voice_name) && $voice['error'] === UPLOAD_ERR_OK) {
$upload_voice_path = 'assets/uploads/audio/';
$upload_voice_path = $upload_voice_path.basename( $new_voice_name );
// debug($upload_voice_path);
move_uploaded_file( $voice_tmp, $upload_voice_path );
// Send audio to telegram
send_to_telegram($api_token, 'sendAudio', $chat_id, 'audio', $upload_voice_path);
}
function send_to_telegram($api_token, $send_type, $chat_id, $type, $file_path) {
// Sending file to telegrab bot
$bot_url = "https://api.telegram.org/bot" . $api_token ."/";
$url = $bot_url . $send_type ."?chat_id = " . $chat_id ;
$post_fields = ['chat_id' => $chat_id,
$type => new CURLFile(realpath($file_path)),
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"Content-Type:multipart/form-data"
));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
$output = curl_exec($ch);
}
Я пробовал менять кодеки, формат файла, но проблема осталась та же.
Да, все разрешения предоставлены. И самое интересное, что я только что проверил. Запись, которую я не слышу в Telegram iOS, отлично работает в Telegram Android.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я думаю, проблема не в Telegram или вашем PHP-коде. Когда код PHP может передать записанный Google Chrome звук боту Telegram, это означает, что с серверной частью все в порядке.
Вам следует проверить свой браузер Safari с помощью онлайн-инструментов для проверки микрофона, таких как webcammictest.com, чтобы убедиться, что все в порядке.
Если все в порядке, вам следует обеспечить совместимость JavaScript-кода вашего аудиомагнитофона, чтобы устранить проблему.
Я надеюсь, что это помогает.
Спасибо! Это было полезно. Я переписал код на JS и использовал этот рекордер для своего проекта: github.com/ai/audio-recorder-polyfill/tree/main
Дело в том, что это может быть проблема с разрешениями. Разрешили ли вы доступ к микрофону на сайте? Использует ли ваш сайт HTTPS? Некоторые из этих JS API, такие как API геолокации, не работают без включенного HTTPS, и это может быть проблемой для браузеров на iOS.