Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a way to play only a portion of an audio file (Seek. Play(duration in ms)). Feature Request. #246

Open
sdattatri opened this issue Oct 24, 2020 · 5 comments

Comments

@sdattatri
Copy link

Hi,
I am building an karaoke type of app. I have one large audio file with the entire song and the lyrics in english. I highlight one line at a time and play the corresponding audio once and then again (at lower volume) for the listener to sing along.

I have the 'start time' and 'duration' of audio corresponding to each line and use seek to start at the correct start time and setTimeout function to stop at the end of the duration. setTimeout however is not very accurate and so there are different periods of lag between devices (On some devices setTimeout seems to get called even before the given msecs, which is quite surprising. So much so, that I am even hesitant to state this!)

Is there a way by which I can play the audio file only for a specified duration? Current code is as follows:

localPlayer.seek(verseTiming.start * 1000, () => {
          localPlayer.play(
            playCallback(
              verseTiming.duration * 1000,
            ),
          );
        });

const playCallback = (msecs) => {
    setTimeout(() => {
        localPlayer.stop(stopCallback());
    }, msecs);
  };

Instead, I would like to use it as follows:

localPlayer.seek(verseTiming.start * 1000, () => {
          localPlayer.play(verseTiming.duration * 1000);
        });

@rustygloves
Copy link

I would like to have the same functionality.

We currently require this to play segments of an audio file with accompanying text animation, essentially in a very similar way to karaoke. Our current workaround is using cuepoints:

updatePlaybackStatus = () => {
    const {currentTime} = this.player;
    const {stopMillis} = this.state;
    if (this.player.isPlaying && stopMillis > 0 && currentTime >= stopMillis) {
      this.player.pause(() => {
        this.setState({stopMillis: 0}, this.playNext);
      });
    }
  };

this.player.seek(cueStart, err => {
        if (err) {
          console.log("player seek() error: ", {err});
        }
        this.player.play(err => {
          if (err) {
            console.log("player play() error: ", {err});
          }
          this.updateInterval = setInterval(() => {
            this.updatePlaybackStatus();
          }, 100);
          this.setState({stopMillis: cueEnd});
        });
      });

I have found the support for seeking is very good on iOS as compared to android devices.
Android devices seem to not work very well with exact millisecond timings.

@rustygloves
Copy link

It seems like there is no react-native library that currently supports this functionality from what I have seen

@disrae
Copy link

disrae commented Jun 19, 2021

Can't this be done with the seek functionality and stop?
I may have misunderstood the statement, maybe the intervalTimer inaccuracies were the main issue.

@rustygloves
Copy link

At the time of posting it could not be reliably achieved with seek and stop. However I have not tested since the intervalTimer inaccuracies were resolved. We have since scrapped this implementation due in part to vary varied performance between Android and iOS devices.

@sdattatri
Copy link
Author

sdattatri commented Jun 21, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants