77

我有一个视频作为网页的背景,我正试图让它循环播放。这是代码:

<video autoplay='true' loop='true' muted='true'>
  <source src='/admin/wallpapers/linked/4ebc66e899727777b400003c' type='video/mp4'></source>
</video>

即使我告诉视频循环播放,它也没有。我还尝试让它与onended属性循环(根据这个 Mozilla 支持线程,我也尝试了一点 jQuery)。到目前为止没有任何效果。是 Chrome 的问题,还是我的代码的问题?

编辑:

我检查了工作副本 ( http://fhsclock-labs.heroku.com/no-violence ) 的网络事件和 HEAD 与我试图开始工作的应用程序。不同之处在于,工作副本是从 Heroku 上的静态资产提供视频(显然是通过 Varnish),而我的工作副本是从 GridFS (MongoDB) 提供的。

Chrome 的 Inspector 的 Network 选项卡显示,在我的应用程序中,视频被请求了 3 次。一次Status是“pending”,第二次是“canceled”,最后一次是200 OK。工作副本只显示了两个请求,一个是 Status is pending,另一个是 206 Partial Content。但是,在视频播放一次后,该请求将更改为“已取消”,并对该视频发出另一个请求。在我的应用程序中,这不会发生。

至于类型,在我的应用程序中,两个是“未定义”,另一个是“视频/mp4”(应该是)。在工作应用程序中,所有请求都是“video/mp4”。

此外,我Resource interpreted as Other but transferred with MIME type undefined.在控制台中收到警告。

我不太确定从哪里开始。我认为问题出在服务器端,因为将文件作为静态资产提供工作正常。可能是服务器未发送正确的内容类型。这可能是 GridFS 的问题。我不知道。

无论如何,来源在这里。感谢您提供的任何见解。

4

9 回答 9

137

啊,我只是偶然发现了这个确切的问题。

事实证明,只有当视频文件由理解部分内容请求的服务器提供时,Chrome 上的元素中的循环(或任何类型的搜索)才有效。即服务器需要尊重包含“范围”标头和 206“部分内容”响应的请求。如果视频足够小以被 chrome 完全缓冲,并且不再进行服务器往返行程,情况也是如此:如果您的服务器第一次没有接受 chrome 的 Range 请求,则视频将不可循环或不可搜索.<video>

所以,是的,GridFS 的一个问题,尽管可以说 Chrome 应该更宽容。

于 2012-03-03T20:02:20.817 回答
22

最简单的解决方法:

$('video').on('ended', function () {
  this.load();
  this.play();
});

'ended'事件在视频到达结尾时触发,将视频video.load()重置为开头,并video.play()在加载后立即开始播放。

这适用于 Amazon S3,您对服务器响应没有太多控制权,并且还解决了与video.currentTime视频缺少长度元数据时无法设置相关的 Firefox 问题。

没有 jQuery 的类似 javascript:

document.getElementsByTagName('video')[0].onended = function () {
  this.load();
  this.play();
};
于 2015-02-25T21:15:35.417 回答
6

看起来它在过去是一个问题,至少有两个已关闭的错误,但都表示它已修复:

http://code.google.com/p/chromium/issues/detail?id=39683

http://code.google.com/p/chromium/issues/detail?id=18846

由于 Chrome 和 Safari 都使用基于 webkit 的浏览器,您也许可以使用其中一些变通方法:http: //blog.millermedeiros.com/2011/03/html5-video-issues-on-the-ipad-and-how -解决他们/

function restartVideo(){
vid.currentTime = 0.1; //setting to zero breaks iOS 3.2, the value won't update, values smaller than 0.1 was causing bug as well.
vid.play();
}

//loop video
vid.addEventListener('ended', restartVideo, false);
于 2011-11-11T01:32:27.973 回答
5

万一以上答案都不能帮助您,请确保您没有在检查禁用缓存选项的情况下运行检查器。由于 Chrome 从缓存中抓取视频,它基本上会工作一次。在意识到这是原因之前仅调试了 20 分钟。供参考,所以我知道我不是唯一一个别人的铬错误报告

于 2016-04-11T23:15:44.420 回答
3

我的情况:

我有完全相同的问题,但是单独更改响应消息的标题并没有做。没有循环、重播或搜索。纯粹的停止也不起作用,但这可能是我的配置。

回答:

根据一些网站(再也找不到它们),它也可以在视频结束后立即触发 load() 方法,并且在下一个应该开始之前。这应该重新加载导致再次工作的视频/音频元素的源。

@约翰

请注意,您的答案/链接是正常的错误,而不是专注于这个问题。使用服务器/网络服务器是导致此问题的原因。而这些链接描述的错误是不同类型的。这也是为什么答案不起作用的原因。

我希望它有所帮助,我仍在寻找解决方案。

于 2012-12-05T09:45:04.490 回答
2

我知道这与所提出的问题并不完全相关,但是如果有人在遇到类似问题时遇到此问题,请确保您的资源正确有序。

我正在加载一个mp4和一个webm文件,并注意到视频没有在 Chrome 中循环播放。这是因为该webm文件是第一个source列出的,所以 Chrome 正在加载webm文件而不是mp4.

希望对遇到此问题的其他人有所帮助。

<video autoplay loop>
    <source src="/path-to-vid/video.mp4" type="video/mp4">
    <source src="/path-to-vid/video.webm" type="video/webm">
</video>
于 2016-01-13T20:11:38.470 回答
1

它超级蹩脚,但保管箱使用正确的状态码。所以上传到Dropbox并用dl替换www。

因此,使用 Dropbox url 视频可以正常播放。

于 2015-04-11T01:31:29.557 回答
1

我遇到了同样的问题,并且通过流式传输内容不可避免地解决了问题。

例如,这是请求流式路由的带有 PHP laravel Blade html 代码的代码:

<video>
    <source src="{{route('getVideoStream',$videoId)}}" type="video/mp4"/>
</video>

在控制器中,我将流式传输视频并将其作为 laravel 流函数返回:

   public function getVideoStream($videoId){

        $path = $pathOfVideo;

        $headers = [
            'Content-Type' => 'video/mp2t',
            'Content-Length' => File::size($path),
            'Content-Disposition' => 'attachment; filename="start.mp4"'
        ];

        $stream = new VideoStream($path);

        return response()->stream(function () use ($stream) {
            $stream->start();
        });
    }

VideoStream Class 是我从 GitHub gist中找到的流媒体类:

class VideoStream
{
    private $path = "";
    private $stream = "";
    private $buffer = 102400;
    private $start = -1;
    private $end = -1;
    private $size = 0;

    function __construct($filePath)
    {
        $this->path = $filePath;
    }

    /**
     * Open stream
     */
    private function open()
    {
        if (!($this->stream = fopen($this->path, 'rb'))) {
            die('Could not open stream for reading');
        }

    }

    /**
     * Set proper header to serve the video content
     */
    private function setHeader()
    {
        ob_get_clean();
        header("Content-Type: video/mp4");
        header("Cache-Control: max-age=2592000, public");
        header("Expires: " . gmdate('D, d M Y H:i:s', time() + 2592000) . ' GMT');
        header("Last-Modified: " . gmdate('D, d M Y H:i:s', @filemtime($this->path)) . ' GMT');
        $this->start = 0;
        $this->size = filesize($this->path);
        $this->end = $this->size - 1;
        header("Accept-Ranges: 0-" . $this->end);

        if (isset($_SERVER['HTTP_RANGE'])) {

            $c_start = $this->start;
            $c_end = $this->end;

            list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
            if (strpos($range, ',') !== false) {
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header("Content-Range: bytes $this->start-$this->end/$this->size");
                exit;
            }
            if ($range == '-') {
                $c_start = $this->size - substr($range, 1);
            } else {
                $range = explode('-', $range);
                $c_start = $range[0];

                $c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $c_end;
            }
            $c_end = ($c_end > $this->end) ? $this->end : $c_end;
            if ($c_start > $c_end || $c_start > $this->size - 1 || $c_end >= $this->size) {
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header("Content-Range: bytes $this->start-$this->end/$this->size");
                exit;
            }
            $this->start = $c_start;
            $this->end = $c_end;
            $length = $this->end - $this->start + 1;
            fseek($this->stream, $this->start);
            header('HTTP/1.1 206 Partial Content');
            header("Content-Length: " . $length);
            header("Content-Range: bytes $this->start-$this->end/" . $this->size);
        } else {
            header("Content-Length: " . $this->size);
        }

    }

    /**
     * close curretly opened stream
     */
    private function end()
    {
        fclose($this->stream);
        exit;
    }

    /**
     * perform the streaming of calculated range
     */
    private function stream()
    {
        $i = $this->start;
        set_time_limit(0);
        while (!feof($this->stream) && $i <= $this->end) {
            $bytesToRead = $this->buffer;
            if (($i + $bytesToRead) > $this->end) {
                $bytesToRead = $this->end - $i + 1;
            }
            $data = fread($this->stream, $bytesToRead);
            echo $data;
            flush();
            $i += $bytesToRead;
        }
    }

    /**
     * Start streaming video content
     */
    function start()
    {
        $this->open();
        $this->setHeader();
        $this->stream();
        $this->end();
    }
}
于 2019-11-11T04:35:34.053 回答
1

对于 9 年后访问此页面的任何人,如果上述所有答案都不起作用:我也遇到了这个问题,我认为问题的根源是我的浏览器或服务器。

我后来注意到互联网上其他使用循环视频的网站在循环视频方面没有问题。为了解决问题,我从其中一个站点下载了一个随机视频,我访问并上传到我自己的服务器上,很高兴地发现它正在工作,所以问题的根源似乎是我正在使用的视频。

然后我用一个在线视频转换器网站修复了我的视频(不想特别宣传任何内容,但谷歌快速研究的第一个确实有效),唉,这解决了这个问题。

我不确定问题的真正原因是什么。我确实假设我的客户交给我的原始视频存在转换或压缩错误。

于 2021-03-16T18:50:28.927 回答