Як створити в реальному часі сигнали SoundCloud у React Native

Вступ

SoundCloud - це платформа для потокового передавання музики та подкастів для прослуховування мільйонів автентичних композицій. Вони мають справді інтерактивний інтерфейс для відтворення / прослуховування композицій.

Найважливішою особливістю їх інтерфейсу є показ ходу доріжки на основі її частотної форми сигналу. Це допомагає користувачам визначити природу цього.

У них також є публікація в блозі, де описується, як використовувати осцилограм на основі його зображення. Важко використовувати однакові методи для генерації сигналу в додатку React Native . Їх пакет Waveform.js SDK перетворює форму сигналу у плаваючі крапки для візуалізації на полотні HTML5 і в даний час вже не працює.

У цій статті ми обговоримо, як використовувати ту саму форму сигналу для наших програм React Native.

Чому я повинен використовувати сигнали SoundCloud?

  • Форма сигналу SoundCloud виглядає більш вражаюче, ніж старий нудний спосіб відображення індикатора прогресу.
  • Попередньо завантажена форма сигналу дасть користувачеві уявлення про різні частоти, присутні в пісні.
  • Також набагато простіше показати відсоток буферизованої доріжки на формі сигналу, а не показувати його на порожньому рядку прогресу.

Давайте дізнаємось більше про форми сигналу SoundCloud

SoundCloud надає waveform_urlAPI в своїх треках.

  • Кожна доріжка має свого унікального waveform_url.
  • waveform_urlМістить посилання на зображення піднятого над хмарою.

Приклад - //w1.sndcdn.com/PP3Eb34ToNki_m.png

На сьогодні кожен аргумент є статичним, отже, він непридатний для використання в поточному стані. Тому нам потрібно заново створити форму сигналу на його основі, використовуючи контейнери React Native, щоб мати доступ до подій дотику, стилів тощо.

Починаємо

Ось список речей, які вам знадобляться:

  • d3-шкала
  • d3-масив

По-перше, нам потрібна вибірка сигналу. Фокус у тому, щоб замінити .pngна .jsonдля waveform_url. GETЗаклик до неї дасть нам об'єкт відповіді , який містить

  • ширина (ширина сигналу)
  • висота (висота сигналу)
  • зразки (масив)

Для отримання додаткової інформації ви можете спробувати таке посилання //w1.sndcdn.com/PP3Eb34ToNki_m.json.

Пориньте в код

Додайте власний компонент SoundCloudWave

function percentPlayed (time, totalDuration) { return Number(time) / (Number(totalDuration) / 1000)}

Було б краще створити власний компонент SoundCloudWave, який за необхідності можна використовувати в кількох місцях. Ось необхідне props:

  • waveformUrl - об'єкт URL-адреси сигналу (доступний через API Tracks)
  • висота - висота сигналу
  • width - Ширина компонента сигналу
  • percentPlayable - Тривалість доріжки, буферизованої в секундах
  • percentPlayed - Тривалість відтворення композиції в секундах
  • setTime - обробник зворотного дзвінка для зміни поточного часу доріжки.

Отримати зразки

fetch(waveformUrl.replace('png', 'json')) .then(res => res.json()) .then(json => { this.setState({ waveform: json, waveformUrl }) });

Отримайте зразки за допомогою простого GETвиклику API і збережіть результат у state.

Створіть компонент сигналу

import { mean } from 'd3-array';
const ACTIVE = '#FF1844', INACTIVE = '#424056', ACTIVE_PLAYABLE = '#1b1b26'
const ACTIVE_INVERSE = '#4F1224', ACTIVE_PLAYABLE_INVERSE = '#131116', INACTIVE_INVERSE = '#1C1A27'
function getColor( bars, bar, percentPlayed, percentPlayable, inverse) { if(bar/bars.length < percentPlayed) { return inverse ? ACTIVE : ACTIVE_INVERSE } else if(bar/bars.length < percentPlayable) { return inverse ? ACTIVE_PLAYABLE : ACTIVE_PLAYABLE_INVERSE } else { return inverse ? INACTIVE : INACTIVE_INVERSE }}
const Waveform = ( { waveform, height, width, setTime, percentPlayed, percentPlayable, inverse } ) => { const scaleLinearHeight = scaleLinear().domain([0, waveform.height]).range([0, height]); const chunks = _.chunk(waveform.samples, waveform.width/((width - 60)/3)) return (  {chunks.map((chunk, i) => (  { setTime(i) }}>   ))}  ) }

Компонент сигналу працює наступним чином:

  • Чанки ділять samplesоб'єкт на основі того, widthщо користувач хоче відобразити на екрані.
  • Потім фрагменти відображаються у Touchableподії. Стилі як width:2і height: scaleLinearHeight(mean(chunk)). Це генерує meanз d3-array.
  • Метод backgroundColorпередається як метод із різними параметрами getColor. Потім це визначатиме колір, який потрібно повернути, виходячи із встановлених умов.
  • Touchable onPressПодія буде викликати користувальницький обробник передається в нього, щоб встановити нове час пошуку доріжки.

Тепер цей безкомпонентний компонент може бути відтворений для вашого дочірнього компонента як:

render() { const {height, width} = this.props const { waveform } = this.state if (!waveform) return null; return (     )}

Тут один із компонентів сигналу оригінальний, а інвертований, як у програвачі SoundCloud.

Висновок

Here are the links to the react-native-soundcloud-waveform

  • Github
  • npm

I’ve also made an app in react-native — MetalCloud for Metal Music fans where you can see the above component at work.

Here are the links:

  • IOS
  • Android

Thanks for reading. If you liked this article, show your support by clapping to share with other people on Medium.

More of the cool stuff can be found on my StackOverflow and GitHub profiles.

Follow me on LinkedIn, Medium, Twitter for further update new articles.