web-dev-qa-db-fra.com

Google Chrome ne lit pas les vidéos HTML5 sur mobile

Je ne parviens pas à lire une vidéo sur mon mobile Android dans la dernière version de Chrome. Dans d'autres navigateurs comme le navigateur Puffin, la vidéo est en cours de lecture. À des fins de test, j'ai essayé tous les formats courants: 

mp4
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4" type="video/mp4" /></video>
<br />
webm
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE.webm" type="video/webm" /></video>
<br />
ogg
<br />
<video autoplay="autoplay" loop="loop" onended="this.play()"><source src="http://clips.vorwaerts-gmbh.de/VfE.ogv" type="video/ogg" /></video>

https://codepen.io/anon/pen/ozpVNP

 QR Code for CodePen

 Preview on mobile

Selon Mozilla la première vidéo, c'est-à-dire que H.264 + AAC en MP4 devrait être lue. Je prends également cet article en compte et tente de lire les vidéos de JavaScript en plus de tenter de supprimer l'attribut type de la première balise video sans succès. 

Comment puis-je le faire fonctionner dans Chrome on Mobile?

8
modiX

Le problème est que Google veut que les utilisateurs lancent eux-mêmes tous les médias. Ainsi, si vous déboguez le navigateur chrome de votre appareil , vous recevrez l'avertissement "Échec de l'exécution de la lecture sur" HTMLMediaElement ": l'API ne être initié par un geste de l'utilisateur. " Cela signifie donc que vous devez attacher l'initialisation de la vidéo, par exemple, avec un événement de clic

7
Jaco

Il ne semble pas y avoir d’information intéressante à ce sujet, alors j’ai pensé publier mes conclusions.

J'ai débogué la lecture vidéo html5 sur les ordinateurs de bureau et mobiles Chrome sur un Android 5.0.1 Samsung S4 avec Chrome 61 et le navigateur intégré, ainsi que Safari 9 et 11, à l'aide d'une lecture/pause javascript automatique écrite dans AngularJS (ci-dessous). La vidéo est intégrée dans un carrousel, elle est donc parfois visible, parfois non. En résumé:

  • Je recommanderais d'avoir les formats webm (vp8/vorbis) et mp4 (h264/aac). Ce sont les formats les plus pris en charge et ont une qualité équivalente pour le même débit. ffmpeg peut encoder les deux.
  • Il semble que Chrome mobile préfère webm s’il peut l’obtenir.
  • Si un navigateur lit un fichier lorsque vous le dirigez vers l'URL du fichier, ceci ne signifie pas le signifiera qu'il sera lu s'il est incorporé dans une balise vidéo, bien qu'il vous dira si le format et les codecs sont pris en charge s'il est lu. . Chrome mobile semble très pointilleux sur le fait d'avoir une source vidéo dont la résolution est trop élevée.
  • Safari (et probablement iOS) ne pourra pas lire une vidéo, sauf si elle est servie par un serveur prenant en charge des plages d'octets. Apache, nginx et Amazon S3, par exemple, les prennent en charge, mais de nombreux serveurs Web plus petits (tels que les serveurs WSGI) ne le font pas.
  • L'ordre des vidéos est plus important que l'attribut source media. Toujours avoir d'abord les versions basse résolution d'une vidéo. L'exemple ci-dessous utilise 1920x1080 et 1280x720. Il semble que si le navigateur mobile rencontre une vidéo "trop ​​haute résolution", il arrête simplement de traiter les autres sources et préfère l'affiche.
  • avoir un attribut controls et une lecture manuelle vs jouer avec javascript ne semblent pas faire de différence.
  • l'attribut muted empêche Android de placer une petite icône de haut-parleur dans la barre d'état lors de la lecture, mais hors écran, même lorsque la vidéo ne contient pas de son. En passant, je pense aussi vraiment à votre auditoire si vous avez l'intention de lire automatiquement une vidéo avec son. Personnellement, je pense que c'est une mauvaise idée.
  • l'attribut preload ne semble pas faire beaucoup de différence. Le navigateur aura de toute façon tendance à précharger automatiquement les métadonnées vidéo sélectionnées.
  • le fait d'avoir un attribut source type n'arrête pas la lecture de la vidéo. Si quelque chose aide le navigateur à choisir la source à choisir pour le meilleur
  • l'événement JS video.oncanplay est le meilleur moyen de voir si la balise video a réussi. Si vous n'obtenez pas cela, la vidéo ne sera pas lue, mais le navigateur ne vous dira pas pourquoi.

HTML:

<video class="img-responsive-upscale ng-scope"
  video-auto-ctrl loop muted preload poster="0022.png">
  <source src="vid_small.webm" media="(max-width: 1280px)" type="video/webm">
  <source src="vid_small.mp4" media="(max-width: 1280px)" type="video/mp4">
  <source src="vid.webm" media="(max-width: 1920px)" type="video/webm">
  <source src="vid.mp4" type="video/mp4">
  <img src="0022.png" alt="something"
    title="Your browser does not support the <video> tag">
</video>

Javascript:

<script type="text/javascript">
angular.module('myproducts.videoplay', []).directive('videoAutoCtrl',
  function() {
  return {
    require: '^uibCarousel',
    link: function(scope, element, attrs) {
      var video = element[0];
      var canplay = false;
      var rs = ["HAVE_NOTHING", "HAVE_METADATA", "HAVE_CURRENT_DATA", "HAVE_FUTURE_DATA", "HAVE_ENOUGH_DATA"];
      var ns = ["NETWORK_EMPTY", "NETWORK_IDLE", "NETWORK_LOADING", "NETWORK_NO_SOURCE"];

      function vinfo() {
        console.log("currentSrc = " + video.currentSrc);
        console.log("readyState = " + rs[video.readyState]);
        console.log("networkState = " + ns[video.networkState]);
        bufinfo();
      }

      function bufinfo() {
        // tr is a TimeRanges object
        tr = video.buffered
        if (tr.length > 0) {
          var ranges = ""
          for (i = 0; i < tr.length; i++) {
            s = tr.start(i);
            e = tr.end(i);
            ranges += s + '-' + e;
            if (i + 1 < tr.length) {
              ranges += ', '
            }
          }
          console.log("buffered time ranges: " + ranges);
        }
      }

      video.onerror = function () {
        console.log(video.error);
      }

      video.oncanplay = function () {
        canplay = true;
        if (!playing) {
          console.log("canplay!");
          vinfo();
        }
      }

      var playing = false;
      function playfulfilled(v) {
        console.log("visible so playing " + video.currentSrc.split('/').pop());
        playing = true;
      }

      function playrejected(v) {
        console.log("play failed", v);
      }

      function setstate(visible) {
        if (canplay) {
          if (visible) {
            p = video.play();
            if (p !== undefined) {
              p.then(playfulfilled, playrejected);
            }
          } else if (playing) {
            video.pause();
            console.log("invisible so paused");
            playing = false;
          }
        } else {
          console.log("!canplay, visible:", visible);
          vinfo();
        }
      }
      // Because $watch calls $parse on the 1st arg, the property doesn't need to exist on first load
      scope.$parent.$watch('active', setstate);
    }
  };
});
</script>
6
racitup
<video autoplay loop autobuffer muted playsinline>
     <source src="video/video-hat.mp4" type="video/mp4">
</video>

Le problème a été résolu après la désactivation du mode "Sauvegarde des données" en chrome.