Soundstripe integration
The VideoEditor SDK has two options, making it easier to add Soundstripe to your editor instance.
Option 1. Using the built-in SoundstripeProxyPagingSource#
The simplest solution is to proxy Soundstripe's API (https://docs.soundstripe.com/docs/integrating-soundstripes-content-into-your-application#option-2-proxy-soundstripes-api).
You can configure the endpoint URI in the SoundstripeSettings by setting the proxySourceUri. Additionally, you can add headers that are sent with each request using addHeader(name: String, content: String), which is useful if you need user authentication.
Within your module's build.gradle
file, insert the soundstripe module.
IMGLY.configure {...modules {...include 'ui:soundstripe'}}
After applying the module and syncing with Gradle, you can set your proxySourceUri
in the SoundstripeSettings
of your SettingsList
.
settingsList.configure<SoundstripeSettings> {it.proxySourceUri = "http://example.com/soundsripe"}
Option 2. Using a custom SoundstripePagingSource#
SoundstripePagingSource
is an abstract class that provides a basic implementation of the Paging Library's PagingSource class. It provides the core functionality for loading a page of audio tracks from a data source. The SoundstripePagingSource
class can be extended to create a custom implementation for loading audio tracks from a specific data source.
Implementation#
To implement a custom SoundstripePagingSource
:
- Create a new class that extends
SoundstripePagingSource
. - Override the
onCreate
method. This method is called when the Paging Library is first set up and is used to initialize any resources required by the customSoundstripePagingSource
. - Override the
load
method. This method is called when the Paging Library needs to load a new page of data. In this method, you should load the audio tracks from the data source and return the result as aLoadResult
. - Override the
getRefreshKey
method if required. This method is used to determine the key to be passed to theload
method when the Paging Library needs to refresh the data. - Add you class by setting
SoundstripeSettings.pagingSourceClass=MyProxyPagingSource::class.java
.
Here is an example implementation of a custom SoundstripePagingSource
, showing our SoundstripeProxyPagingSource implementation:
open class SoundstripeProxyPagingSource @Keep constructor(private val query: String = "") : SoundstripePagingSource<Int>() {private val defaultCover = ImageSource.create(R.drawable.imgly_placeholder_album_cover)private lateinit var endpoints: SoundstripeProxyEndpointsoverride fun onCreate(context: Context) {endpoints = stateHandler[SoundstripeSettings::class].proxyApi}override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AudioTrackAsset> {val position = params.key ?: 0return try {val result = endpoints.listSongs(query = query,pageNumber = position,pageCount = params.loadSize).also {it.resolveData()}val data = result.dataval nextKey = if (data.isNotEmpty() && result.links.next != null) {position + (params.loadSize / params.loadSize)} else {null}val nativeAssets = data.mapNotNull { song ->val audioFile = (song.relationships?.audioFiles?.data?.firstOrNull() as? AudioFileDAO)val songUri = audioFile?.attributes?.versions?.mp3 ?: return@mapNotNull nullAudioTrackAsset.createTemporaryAsset(id = "imgly_soundstripe_${song.id}",resolver = SoundstripeProxyAssetResolver(song.id),audioSource = AudioSource.create(Uri.parse(songUri)),title = song.attributes?.title,artist = (song.relationships?.artists?.data?.firstOrNull() as? ArtistDAO)?.attributes?.name,durationInSeconds = audioFile.attributes?.duration?.roundToInt() ?: -1,cover = (song.relationships?.artists?.data?.firstOrNull() as? ArtistDAO)?.attributes?.image?.let { ImageSource.create(Uri.parse(it)) } ?: defaultCover)}LoadResult.Page(data = nativeAssets,prevKey = null, // Only paging forward.// assume that if a full page is not loaded, that means the end of the datanextKey = nextKey)} catch (e: Exception) {e.printStackTrace()LoadResult.Error(e)}}override fun getRefreshKey(state: PagingState<Int, AudioTrackAsset>) = state.anchorPosition!!}