
Мой двоюродный брат застрял, пытаясь сделать диктофон с помощью svelte из какого-то примера кода, который он нашел в Интернете. Я был большим сторонником Svelte / SvelteKit и думал, что помогу ему. Это был мой путь к лучшему пониманию того, как работает Svelte/SvelteKit.
Настройка проекта и контекст
Пример, который мой двоюродный брат пытался внедрить в Svelte, взят с этого сайта. Его замешательство возникло из-за того, что он не понял, куда скопировать/вставить код примера в его демо-версию комплекта svelte (Proof of Concept). . Я просмотрел код и тоже решил использовать в качестве референса пример MDN веб-диктофон. Итак, давайте настроим этот PoC и поможем моему двоюродному брату лучше понять Svelte.
- Настройте новый проект SvelteKit (пропустите, если добавляете в существующий проект), введя следующую команду в терминале
npm init svelte@next audio-recorder
- Следуйте инструкциям, пока ваш проект svelte kit не запустится.
- Итак, нам нужно минимум 3 элемента. HTML-элемент аудио и 2 кнопки (начать и остановить запись)
Наш файл index.svelte должен выглядеть так:
<section> <audio controls /> <button>Record</button> <button>Stop</button> </section>
3. Давайте добавим события нажатия на кнопки
<section>
<audio controls />
<button on:click={startRecording}>Record</button>
<button on:click={stopRecording}>Stop</button>
</section>
На следующем этапе мой двоюродный брат запутался в том, как подключить код и заставить его работать, поэтому я сделаю все возможное, чтобы объяснить, почему я написал код так, как я это сделал.
Svelte и DOM
Таким образом, компоненты, написанные с расширением .svelte, не обязательно привязаны к DOM или странице HTML в тот момент, когда мы думаем. Компонент может быть доступен для нашего приложения, но не отображается автоматически в DOM. По той же причине в React есть метод componentDidMount. Это часть жизненного цикла компонента. В Svelte мы используем onMount, чтобы позволить нам писать код, который мы хотели бы выполнить после присоединения нашего компонента к DOM. (Теперь мы можем получить доступ к окну и документу из onMount)
В примере, которому следовал мой двоюродный брат, это «монтирование» запутано, потому что ванильный JS записывается непосредственно на html-страницу, а не «компилируется», как в нашем примере Svelte, и в этом случае нам нужно ждать, пока наш компонент будет смонтирован. на html-страницу перед вызовом объектов DOM или BOM.
На этом я, надеюсь, объяснил эту концепцию наилучшим образом, давайте добавим суть нашего кода в наш тег script.
Теперь мы импортируем метод onMount из Svelte и создадим первую часть нашего диктофона.
<script>
import { onMount } from 'svelte'
onMount(() => {
})
</script>
...
html markup
В примере кода используется навигатор с цепочкой промисов, но я предпочитаю использовать методы async/ await. (Извините, у меня есть опыт работы с C#)
Example code:
-------------
navigator.mediaDevices.getUserMedia({ audio: true}).then(function(stream) {
var mediaRecorder = new MediaRecorder(stream);
var chunks = [];
mediaRecorder.addEventListener('dataavailable', function(event){
chunks.push(event.data);
});
});
Preferred way:
--------------
const stream = await navigator.mediaDevices.getUserMedia({ audio: true});
let mediaRecorder = null; <-- we declare this outside of onMount
let media = []; <-- also declared outside of onMount
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = e => media.push(e.data);
Я изменил название чанков (мне это не кажется правильным) на носитель, так как это носитель, который мы записали. Я также добавил событие dataavailable в объект mediaRecorder, чтобы добавить захватываемые данные в массив.
На этом этапе ваш скрипт в файле index.svelte должен выглядеть так.
<script>
import { onMount } from 'svelte'
let media = [];
let mediaRecorder = null;
onMount(async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (e) => media.push(e.data)
})
</script>
Последний метод, который нам нужно добавить, — это остановить запись, а затем сохранить звук в нашем аудио-html-элементе и, наконец, сбросить наш медиа-массив, чтобы мы могли быть готовы к записи нового аудиофайла. Затем мы можем подключить наши кнопки к методам щелчка, чтобы начать и остановить запись соответственно.
<script>
import { onMount } from 'svelte'
let media = [];
let mediaRecorder = null;
onMount(async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (e) => media.push(e.data)
mediaRecorder.onstop = function(){
const audio = document.querySelector('audio');
const blob = new Blob(media, {'type' : 'audio/ogg; codecs=opus' });
media = []; <-- We reset our media array
audio.src = window.URL.createObjectURL(blob);
}
})
function startRecording(){ mediaRecorder.start() }
function stopRecording() { mediaRecorder.stop() }
</script>
Теперь вы сможете записывать звук с микрофона вашего устройства.
Я многому научился из этого доказательства концепции и лучше оценил метод onMount, который является частью Svelte и других фреймворков.
Спасибо!