Мой двоюродный брат застрял, пытаясь сделать диктофон с помощью svelte из какого-то примера кода, который он нашел в Интернете. Я был большим сторонником Svelte / SvelteKit и думал, что помогу ему. Это был мой путь к лучшему пониманию того, как работает Svelte/SvelteKit.

Настройка проекта и контекст

Пример, который мой двоюродный брат пытался внедрить в Svelte, взят с этого сайта. Его замешательство возникло из-за того, что он не понял, куда скопировать/вставить код примера в его демо-версию комплекта svelte (Proof of Concept). . Я просмотрел код и тоже решил использовать в качестве референса пример MDN веб-диктофон. Итак, давайте настроим этот PoC и поможем моему двоюродному брату лучше понять Svelte.

  1. Настройте новый проект SvelteKit (пропустите, если добавляете в существующий проект), введя следующую команду в терминале
npm init svelte@next audio-recorder
  1. Следуйте инструкциям, пока ваш проект svelte kit не запустится.
  2. Итак, нам нужно минимум 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 и других фреймворков.

Гитхаб репозиторий

Спасибо!