6

I am trying to create an offline video player that would download video content from my site for later viewing offline via an HTML5 video element. The code below works fine in Chrome for the desktop, but not on mobile (Nexus S smartphone, Nexus 7 tablet, 4.1 since only that runs chrome, which is required for the filesystem api). I am using the filesystem API that is supported by chrome on both the desktop and mobile.

I have confirmed it is correctly storing the file on the mobile device and I can retrieve the file correctly, but for some reason after retrieving the video from the localsystem chrome does not want to play the video. This is true whether I am using the html5 video element or whether I am navigating directly to the filesystem URL. When I use the html5 video element it returns the error media_err_not_supported. I have confirmed that the device can play the video if I navigate directly to it on my server (without first storing it using the filesystem api), so the issue is not a codec or video format problem. I am also using the video/mp4 mime type in both cases.

Again, this works on desktop, but not mobile. Any ideas?

Here is the code we are using:

<!DOCTYPE html >
<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"> </script>
        <script type="text/javascript">
            var _fs;
            var filename = "test3.mp4";
            var diskSpaceRequired = 10 * 1024 * 1024;
            $(document).ready(function () {
                window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
                function onInitFs(fs) {
                    _fs = fs;
                    getVideo(fs);
                }

                if (!!window.requestFileSystem) {

                    window.webkitStorageInfo.requestQuota(
                        window.webkitStorageInfo.PERSISTENT,
                        diskSpaceRequired, // amount of bytes you need
                        function () { },
                        function () {}
                    );
                    window.requestFileSystem(window.PERSISTENT, diskSpaceRequired, onInitFs, function () { alert('error'); });
                } else {
                    alert('not supported');
                }

                $("#play").on('click', playVideo);
                $("#ourVideo").on('error', function(e) { console.log('ERROR!!!', e, arguments);
                  console.log($("#ourVideo")[0].error);
                 });
            });

            function playVideo() {
               _fs.root.getFile(filename, {}, function (fileEntry) {
                    $("#ourVideo").attr('src', fileEntry.toURL());
                    fileEntry.file(function (file) {
                      var reader = new FileReader();
                      reader.onloadend = function (e) {
                        $("#ourVideo").get(0).play();
                      };
                      reader.readAsText(file);
                    }, errorHandler);

                }, errorHandler);
            }

            function getVideo(fs) {
                fs.root.getFile(filename, { create: true }, function (fileEntry) {
                    fileEntry.createWriter(function (fileWriter) {
                        fetchResource(fileWriter);
                    }, errorHandler);

                }, errorHandler);
            }

            function errorHandler(e) {
                console.log('error', e);
            }

            function fetchResource(fileWriter) {
                console.log('fetchresource');
                var xhr = new XMLHttpRequest();
                xhr.responseType = "arraybuffer";
                xhr.open("GET", "http://mydomain.com/trailer.mp4", true);

                xhr.onload = function(e) {
                    if (this.status == 200) {
                        var bb = new WebKitBlobBuilder();
                        bb.append(this.response);

                        var blob = bb.getBlob("video\/mp4");
                        fileWriter.write(blob);
                    } else  {
                      console.log(this.status);
                    }
                };
                xhr.send();
            }            

        </script>
        <title>foo</title>
    </head>
    <body>


        <input type="button" value="Play Video" id="play"/>
            <video id="ourVideo" controls="">
                <source id="vidSource"  type="video/mp4"/>
            </video>

    </body>
</html>
Jim Cooper
  • 5,113
  • 5
  • 30
  • 35
  • What is the full path to the file once it's been downloaded? Have you definitely been able to play *that* file, as opposed to a separately-downloaded copy elsewhere? – Reuben Scratton Aug 14 '12 at 16:01
  • When the call is made to fileEntry.toURL() in the code above, it returns a URL like this: filesystem:mydomain.com/persistent/test3.mp4. And, yes, if I navigate directly to the URL that it is downloading from (mydomain.com/trailer.mp4 in the example above) it plays the video just fine. – Jim Cooper Aug 15 '12 at 15:26
  • See if you can play the video. Take it either off the device and play it Or play it from a movie player on the device. – Nate-Wilkins Sep 02 '12 at 22:06
  • Nate, the video does play fine. The fundamental issue is that the browser is not translating the filesystem:http://foo.bar/video.mp4 to a local filesystem path, so Android's player barfs on the mangled path. From looking at Chromium bug reports I *think* this got fixed in Chrome 20.0, but the current Android Chrome is still stuck at version 18. – Reuben Scratton Sep 03 '12 at 09:19
  • Yes the video plays fine, anxiously waiting for the release of Chrome 20.0. :) – Jim Cooper Sep 27 '12 at 16:18
  • have you solved the issue now? because i am running in the same problem, playing from remote url works fine, on filesystem it doesnt play – pfried Apr 28 '13 at 08:46
  • Ok found the bug report: https://code.google.com/p/chromium/issues/detail?id=180541 – pfried Apr 28 '13 at 09:14

1 Answers1

0

The problem looks like your android chrome coudn't access the android file system correctly, For that you can use nanoHttpd server for access android local files in device or sdcard. for NanoHttpd server use this one class in your application and pass the media file location as http://localhost:8081/sdcard/(your_media_location).mp4

or get nanoHttpd from https://gist.github.com/1893396

I think this is more accurate to access sdcard files than directly calling for them


try change html part to

</head>
<body>


    <input type="button" value="Play Video" id="play"/>
        <video id="ourVideo" controls="">                
             <source src="video1.mp4" type= "video/mp4">
             <source src="video1.ogv" type= "video/ogg">
        </video>

</body>

you can convert your mp4 to ogv using http://video.online-convert.com/convert-to-ogg and put ogv file in the same location in mp4

**for more information check out these http://www.broken-links.com/2010/07/08/making-html5-video-work-on-android-phones/

HTML5 <video> element on Android does not play

Community
  • 1
  • 1
UdayaLakmal
  • 4,035
  • 4
  • 29
  • 40
  • This is HTML, not a native application. – Reuben Scratton Sep 03 '12 at 09:17
  • "I am trying to create an offline video player" I thought this is kind of android application, by the way do you try add ogv format with the mp4, when i try with android webview that didn't play mp4 without ogv, i updated my answer – UdayaLakmal Sep 04 '12 at 10:33
  • IIRC Android supports MP4 as a container format but doesn't support all H.264 profiles. I can't remember what the state of Ogg Vorbis support was or is. The *playing* of videos isn't an issue here - we have videos playing fine, providing they're streamed. It's playing from HTML5 offline storage that's broken. – Reuben Scratton Sep 04 '12 at 13:40