如何在React Native中制作实时SoundCloud波形

郎和通
2023-12-01

by Pritish Vaidya

通过Pritish Vaidya

如何在React Native中制作实时SoundCloud波形 (How to make realtime SoundCloud Waveforms in React Native)

介绍 (Introduction)

SoundCloud is a music and podcast streaming platform for listening to millions of authentic tracks. They have a really interactive interface for playing / listening to the tracks.

SoundCloud是一个音乐和播客流媒体平台,用于收听数百万条真实曲目。 他们有一个真正的交互式界面,用于播放/收听曲目。

The most important feature in their interface is showing the progress of the track based on its frequency waveform. This helps the users to identify the nature of it.

他们界面中最重要的功能是根据轨道的频率波形显示轨道的进度 这可以帮助用户识别其性质。

They also have a blog post which describes how to use the waveform based on its image. It is hard to use the same techniques to generate the waveform in a React Native app. Their Waveform.js SDK translates a waveform into floating points to render on an HTML5 canvas and is currently no longer operational.

他们也有一篇博客文章 ,描述了如何根据图像使用波形。 在React Native应用程序中很难使用相同的技术来生成波形。 他们的Waveform.js SDK 将波形转换为浮点以在HTML5画布上呈现,并且目前无法使用。

In this article we’ll discuss how to use the same waveform for our React Native apps.

在本文中,我们将讨论如何在React Native应用程序中使用相同的波形。

为什么要使用SoundCloud的波形? (Why Should I use SoundCloud’s Waveforms?)

  • The SoundCloud’s waveform looks more impressive than the old boring way of showing the progress bar.

    SoundCloud的波形看起来比显示进度条的老式方法更令人印象深刻

  • The pre-loaded waveform will give the user an idea of the different frequencies present in the song.

    预加载的波形将使用户了解歌曲中存在的不同频率。
  • It is also much easier to show the buffered track percentage on a waveform rather than showing it on a blank progress bar.

    在波形上显示缓冲的轨迹百分比比在空白进度条上显示要容易得多。

让我们进一步了解SoundCloud的波形 (Let’s learn more about SoundCloud’s Waveforms)

The SoundCloud provides a waveform_url in its tracks API.

SoundCloud在其tracks API中提供了一个waveform_url

  • Each track has its own unique waveform_url .

    每条磁道都有其自己唯一的waveform_url

  • The waveform_url contains a link to the image hoisted over the cloud.

    waveform_url包含指向云上悬挂的图像的链接。

Example — https://w1.sndcdn.com/PP3Eb34ToNki_m.png

示例— https://w1.sndcdn.com/PP3Eb34ToNki_m.png

As of now, every argument is static hence it is unusable in this current state. Therefore we need to re-create the waveform based on it using React Native’s containers in order to have access to the touch events, styles etc.

到目前为止,每个参数都是静态的,因此在当前状态下无法使用。 因此,我们需要使用React Native的 容器基于该波形重新创建波形,以便能够访问触摸事件,样式等。

入门 (Getting Started)

Here is a list of stuff that you will need:

这是您将需要的东西的列表:

First, we need the sampling of the waveform. The trick is to replace .png with .json for the waveform_url . A GET call to it would give us a response object that contains

首先,我们需要对波形进行采样。 诀窍是将.png替换为.json ,以使用waveform_url 。 对其的GET调用将为我们提供一个包含以下内容的响应对象

  • width (Width of the waveform)

    宽度 (波形宽度)

  • height (Height of the waveform)

    高度 (波形的高度)

  • samples (Array)

    样本 (数组)

For more info, you can try out the following link https://w1.sndcdn.com/PP3Eb34ToNki_m.json.

有关更多信息,您可以尝试以下链接https://w1.sndcdn.com/PP3Eb34ToNki_m.json

深入研究代码 (Dive into the code)

添加自定义SoundCloudWave组件 (Add a Custom SoundCloudWave Component)

function percentPlayed (time, totalDuration) { return  Number(time) / (Number(totalDuration) / 1000)}
<SoundCloudWave  waveformUrl={waveform_url}  height={50}  width={width}  percentPlayable={percentPlayed(bufferedTime, totalDuration)}   percentPlayed={percentPlayed(currentTime, totalDuration)}  setTime={this.setTime}/>

It would be better to create a custom SoundCloudWave component that can be used in multiple places as required. Here are the required props:

最好创建一个自定义的SoundCloudWave组件,该组件可以根据需要在多个地方使用。 这是必需的props

  • waveformUrl — The URL object to the waveform (accessible through the Tracks API)

    waveformUrl波形的URL对象(可通过Tracks API访问)

  • height — Height of the waveform

    height —波形的高度

  • width — Width of the waveform component

    width —波形分量的宽度

  • percentPlayable — The duration of the track buffered in seconds

    percentPlayable —轨道的持续时间(以秒为单位)

  • percentPlayed — The duration of the track played in seconds

    percentPlayed —曲目播放的持续时间(以秒为单位)

  • setTime — The callback handler to change the current track time.

    setTime —更改当前跟踪时间的回调处理程序。

获取样品 (Get the samples)

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

Get the samples by using a simple GET API call and store the result in the state.

通过使用简单的GET API调用获取样本并将结果存储在state

创建波形组件 (Create a Waveform Component)

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 (        <View style={[{          height,          width,          justifyContent: 'center',          flexDirection: 'row',         },         inverse && {          transform: [            { rotateX: '180deg' },            { rotateY: '0deg'},          ]         }        ]}>         {chunks.map((chunk, i) => (           <TouchableOpacity key={i} onPress={() => {             setTime(i)           }}>            <View style={{              backgroundColor: getColor               (                 chunks,                 i,                 percentPlayed,                 percentPlayable,                 inverse               ),              width: 2,              marginRight: 1,              height: scaleLinearHeight(mean(chunk))             }}            />          </TouchableOpacity>         ))}        </View>      )  }

The Waveform Component works as follows:

波形组件的工作原理如下:

  • The Chunks split the samples object based on the width that the user wants to render on the screen.

    块根据用户想要在屏幕上渲染的width拆分samples对象。

  • The Chunks are then mapped into a Touchable event. The styles as width:2 and height: scaleLinearHeight(mean(chunk)). This generates the mean from the d3-array.

    然后将块映射到一个Touchable事件。 样式为width:2height: scaleLinearHeight(mean(chunk)) 。 这从d3-array生成mean

  • The backgroundColor is being passed as a method with different parameters to the getColor method. This will then determine the color to return based on the conditions set.

    backgroundColor作为具有不同参数的方法传递给getColor方法。 然后,将根据设置的条件确定要返回的颜色。

  • The Touchable onPress event will call the custom handler passed into it, to set the new seek time of the track.

    Touchable onPress事件将调用传递给它的自定义处理程序,以设置轨道的新查找时间

Now this stateless component can be rendered to your child component as:

现在,该无状态组件可以呈现为您的子组件,如下所示:

render() {  const {height, width} = this.props  const { waveform } = this.state  if (!waveform) return null;  return (     <View style={{flex: 1, justifyContent: 'center'}}>       <Waveform         waveform={waveform}         height={height}         width={width}         setTime={this.setTime}         percentPlayed={this.props.percent}         percentPlayable={this.props.percentPlayable}         inverse       />       <Waveform         waveform={waveform}         height={height}         width={width}         setTime={this.setTime}         percentPlayed={this.props.percent}         percentPlayable={this.props.percentPlayable}         inverse={false}       />     </View>    )}

Here one of the waveform component is original and one inverted as in the SoundCloud’s player.

在这里,波形分量之一是原始波形,而另一波形分量是SoundCloud播放器中的波形分量。

结论 (Conclusion)

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

这是react-native-soundcloud波形的链接

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

我还用Reactn -native制作了一个应用程序-MetalCloud for Metal Music粉丝 ,您可以在其中看到上面的组件。

Here are the links:

这里是链接:

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

谢谢阅读。 如果您喜欢这篇文章,请鼓掌与Medium上的其他人分享以表示支持。

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

在我的StackOverflowGitHub个人资料中可以找到更多有趣的东西。

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

LinkedInMediumTwitter上关注我,以获取更多更新的新文章。

翻译自: https://www.freecodecamp.org/news/how-to-make-realtime-soundcloud-waveforms-in-react-native-4df0f4c6b3cc/

 类似资料: