Run react-native info in your project and share the content.
React Native Environment Info:
System:
OS: macOS 10.14.4
CPU: (8) x64 Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
Memory: 50.72 MB / 8.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 11.13.0 - /usr/local/bin/node
Yarn: 1.15.2 - /usr/local/bin/yarn
npm: 6.7.0 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2
Android SDK:
API Levels: 27, 28
Build Tools: 27.0.3, 28.0.3
System Images: android-27 | Intel x86 Atom_64, android-28 | Google APIs Intel x86 Atom
IDEs:
Android Studio: 3.3 AI-182.5107.16.33.5199772
Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild
npmPackages:
react: 16.8.3 => 16.8.3
react-native: 0.59.3 => 0.59.3
npmGlobalPackages:
react-native-cli: 2.0.1
What react-native-track-player version are you using?
^1.1.3
Hi everyone. So I am making a react-native project streaming music. My application works fine with short track, but when it comes to longer ( from 20 minutes to hours ), the problem arises:
TrackPlayer.getDuration() return 0. I initialized track with duration property so it is not the problem when Track Player try to calculate the length of track.TrackPlayer.play(); method, state of TrackPlayer changes but the music doesn't come out. In some scenario, it comes back to 'loading' state.I'm sure it is the problem with the Track Player because I let the player wait for minutes but it is still loading, but when i change the track, the problem immediately solves.
import React, { Component } from 'react';
import TrackPlayer from 'react-native-track-player';
import { Header, AlbumArt, TrackDetails, SeekBar, PlaybackControl, Spinner } from './common'
import { TextInput, Button, SafeAreaView, Text, View } from 'react-native';
import axios from 'axios';
import memoize from "memoize-one";
import moment from 'moment';
export default class PlayScreen extends Component {
constructor(props) {
super(props);
this.state = {
track: null,
paused: true,
isLoading: false,
shuffleOn: false,
repeatOn: true
};
}
onPressPause() {
this.setState({ paused: true });
TrackPlayer.pause();
}
onPressPlay() {
this.setState({ paused: false })
TrackPlayer.play();
}
onPressRepeat() {
this.setState((state) => {
return {repeatOn: !this.state.repeatOn}
})
}
async onPressBack() {
await TrackPlayer.skipToPrevious();
}
async onPressForward() {
await TrackPlayer.skipToNext();
}
initializeTrack(videoId) {
// initialize track ( loading track from url )
return track;
}
async addAndPlay(track) {
TrackPlayer.add(track).then(async (result) => {
/**
* PURPOSE: wait until track player have finished loading. Currently not work as expected
*/
console.log('add track result: ' + result);
TrackPlayer.getState().then((playerState) => {
console.log('track state ' + playerState)
this.setState({ isLoading: false })
})
});
await TrackPlayer.skip(track.id)
this.onPressPlay();
}
memoizedLoad = memoize(async (videoId) => {
if(!videoId)
return;
TrackPlayer.pause();
this.setState({ isLoading: true })
let track = await this.initializeTrack(videoId)
this.addAndPlay(track)
})
async getTheTrackQueue() {
let tracks = await TrackPlayer.getQueue();
console.log(tracks)
TrackPlayer.getState().then((result) => console.log(result))
}
async componentDidUpdate() {
this.memoizedLoad(this.props.navigation.getParam('videoId'));
}
componentWillUnmount() {
// Removes the event handler
}
async componentDidMount() {
this.onTrackChange = TrackPlayer.addEventListener('playback-track-changed', async (data) => {
let track = await TrackPlayer.getTrack(data.nextTrack);
this.setState({track});
this.setState({ paused: false });
});
this.memoizedLoad(this.props.navigation.getParam('videoId'));
}
render() {
return (
<SafeAreaView style={{ flex: 1, backgroundColor: 'gray' }}>
<Header
message="playing from fly"
onQueuePress={this.getTheTrackQueue.bind(this)}
/>
<AlbumArt url={!this.state.track ? "" : this.state.track.thumbnail.url} />
<TrackDetails
title={!this.state.track ? "" : this.state.track.title.slice(0, 30)}
/>
<SeekBar
trackLength={!this.state.track ? 0 :this.state.track.duration}
/>
<PlaybackControl
paused={this.state.paused}
shuffleOn={this.state.shuffleOn}
repeatOn={this.state.repeatOn}
onPressPause={this.onPressPause.bind(this)}
onPressPlay={this.onPressPlay.bind(this)}
onPressRepeat={this.onPressRepeat.bind(this)}
forwardDisabled={false}
backwardDisabled={false}
shuffleDisabled={true}
onForward={this.onPressForward.bind(this)}
onBack={this.onPressBack.bind(this)}
/>
{this.state.isLoading ?
<Spinner /> : <View />
}
<Button title='get duration' onPress={async() => {
console.log(await TrackPlayer.getDuration())
}}/>
<Button title='force play' onPress={async() => {
await TrackPlayer.remove(this.state.track.id)
TrackPlayer.skip(this.state.track.id)
}}/>
<Button title='remove current' onPress={async() => {
await TrackPlayer.remove(this.state.track.id)
}}/>
</SafeAreaView>
);
}
}
Same problem here, In my case it is even worse because I am playing streams and RNTrackPlayer can never guess the duration.
I must also mention this problem is only present in iOS and my Android app is working properly.
(if you are using the version 1.1.4) Maybe you should try to add
waitForBuffer: true
to PlayerOptions.
from some reason it is not documented, but it is part of the api
Any update on this?
I was able to solve my problem with something like this https://github.com/react-native-kit/react-native-track-player/issues/533#issuecomment-492206711
Most helpful comment
(if you are using the version 1.1.4) Maybe you should try to add
to PlayerOptions.
from some reason it is not documented, but it is part of the api