0

I have an html Video and I am controlling the playback speed depending on the position of the mouse. When the mouse position goes into minus numbers I get this error:

Failed to set the 'playbackRate' property on 'HTMLMediaElement': The provided playback rate (-0.01) is not in the supported playback range.

This is because minus numbers do not work as a playback rate. It would be cool if the video played backwards when the value goes less then zero. How can I achieve this?

$("body").mousemove(function(event){            
    var relX = event.pageX - $(this).offset().left;
    var relY = event.pageY - $(this).offset().top;
    $('.slow-video').prop({
       playbackRate: ((relY/200)+(relX/300)-2)
    });
});
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • You could have 2 video sources, and when the playback rate is negative, activate the 2nd video source, that will be rendered in reverse, and play it – Emanuel Vintilă Mar 05 '21 at 10:43
  • 1
    Modern video codecs don't allow for playing in reverse. There are other questions on SO with the same issue and conclusion. Solution above to have two different pre-encoded videos sounds like your best bet. – freedomn-m Mar 05 '21 at 10:44
  • 1
    Does this answer your question? [Is it possible to play HTML5 video in reverse?](https://stackoverflow.com/questions/5277293/is-it-possible-to-play-html5-video-in-reverse) – freedomn-m Mar 05 '21 at 10:45

1 Answers1

1

As you've discovered, you cannot set a video playbackRate to be negative. However you can 'animate' through the frames of a video in any direction required using a timer or interval.

Also note that I would suggest that using the mouse position to control playback direction is not the most user-friendly, nor accurate. In the example below I used a slider input as it offers much finer control. Try this:

let playbackInterval;
let $video = $('video');
let video = $video[0];
let $rateLabel = $('#rate-value');

video.volume = 0.1; // just for testing

let $rate = $("#rate").on('input', e => {
  clearInterval(playbackInterval);
  var rate = parseFloat(e.target.value / 100);
  $rateLabel.text(`${Math.round(rate * 100) / 10}x`);

  if (rate === 0.1) {
    video.play();
  } else {
    video.pause();
    playbackInterval = setInterval(function() {
      video.currentTime = Math.max(0, video.currentTime + rate);      
      if (video.currentTime <= 0 || video.currentTime >= video.duration) {
        clearInterval(playbackInterval);
      }
    }, 100);
  }
});

$video.on('play', () => {
  $rate.val(10).trigger('input');
  clearInterval(playbackInterval)
});
video {
  width: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<video autobuffer controls>
  <source id="mp4" src="http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4" type="video/mp4">
</video><br /> Playback rate:
<input type="range" id="rate" min="-10" max="20" step="1" value="10" />
<label id="rate-value">1x</label>
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339