阻止下载HTML5视频(右键单击保存)?

问题描述 投票:142回答:18

如何从浏览器的右键菜单中禁用“将视频另存为...”以防止客户端下载视频?

是否有更完整的解决方案阻止客户端直接访问文件路径?

javascript html5 menu html5-video right-click
18个回答
201
投票

你不能。那是因为浏览器的设计目的是:服务内容。但是你可以下载更难。

首先,你可以禁用contextmenu event,即“右键单击”。这样可以防止您的常规skiddie通过右键单击并另存为来公然翻录您的视频。但是他们可能只是禁用JS并绕过它或通过浏览器的调试器找到视频源。另外这是糟糕的用户体验。上下文菜单中有许多合法的东西,而不仅仅是另存为。

您还可以使用自定义视频播放器库。他们中的大多数都实现了根据您的喜好自定义上下文菜单的视频播放器。因此,您没有获得默认的浏览器上下文菜单。如果他们确实提供类似于另存为的菜单项,您可以禁用它。但同样,这是一个JS解决方法。弱点与之前的选项类似。

另一种方法是使用HTTP Live Streaming提供视频。它本质上做的是将视频切成块并一个接一个地服务。这是大多数流媒体网站提供视频的方式。因此,即使您设法另存为,也只能保存一个块,而不是整个视频。收集所有块并使用一些专用软件缝合它们需要更多的努力。

另一种技术是paint <video> on <canvas>。在这种技术中,使用一点JavaScript,你在页面上看到的是一个<canvas>元素渲染来自隐藏的<video>的帧。因为它是<canvas>,上下文菜单将使用<img>的菜单,而不是<video>。您将获得“将图像另存为”而不是“将视频另存为”。

您也可以使用CSRF tokens。您的服务器会在页面上发送一个令牌。然后,您可以使用该令牌来获取视频。您的服务器在提供视频之前检查它是否是有效令牌,或者获取HTTP 401。我们的想法是,您只能通过拥有一个令牌来获取视频,如果您来自该页面,则只能获得该令牌,而不是直接访问该视频网址。

在一天结束时,我只是将视频上传到第三方视频网站,例如YouTube或Vimeo。他们拥有良好的视频管理工具,优化了设备的播放效果,并且他们努力防止他们的视频因为您的努力而被扯掉。


3
投票

+1简单和跨浏览器方式:您还可以使用css z-index和opacity将透明图片放在视频上。因此用户将在上下文菜单中看到“将图片另存为”而不是“保存视频”。


3
投票

<body oncontextmenu="return false;"> 

不再有效。截至2018年6月的Chrome和Opera在时间轴上有一个允许直接下载的子菜单,因此用户无需右键单击即可下载该视频。有趣的是Firefox和Edge没有这个......


2
投票

使用Vimeo等服务:登录Vimeo > Goto Video > Settings > Privacy > Mark as Secured,并选择嵌入域。设置嵌入域后,除非从指定的域连接,否则不允许任何人嵌入视频或从浏览器显示视频。因此,如果您的服务器上有一个安全的页面,它会在iframe中加载Vimeo播放器,这使得它很难绕过。


2
投票

首先要意识到完全阻止视频下载是不可能的,你所能做的就是让它变得更加困难。即你隐藏了视频的来源。

Web浏览器会暂时将视频下载到缓冲区中,因此如果可以阻止下载,您也可以阻止视频被查看。

您还应该知道,世界总人口的<1%将能够理解源代码,无论如何都会使其相当安全。这并不意味着你也不应该把它隐藏在源头中 - 你应该这样做。

你不应该禁用右击,甚至更少你应该显示一条消息说"You cannot save this video for copyright reasons. Sorry about that."。正如this answer所建议的那样。

这对用户来说可能非常烦人并且令人困惑。除此之外;如果他们在浏览器上禁用JavaScript,他们将能够右键单击并保存。

这是你可以使用的CSS技巧:

video {
    pointer-events: none;
}

无法在浏览器中关闭CSS,保护您的视频而不实际禁用右键单击。然而,一个问题是controls也无法启用,换句话说,它们必须设置为false。如果您要设置自己的播放/暂停功能或使用具有与video标签分开的按钮的API,那么这是一个可行的选项。

controls也有一个下载按钮,所以使用它也不是一个好主意。

这是一个JSFiddle的例子。


如果您要使用JavaScript禁用右键单击,那么也会在JavaScript中存储视频源。这样,如果用户禁用JavaScript(允许右键单击),视频将无法加载(它还会使视频源隐藏得更好)。

来自TxRegex answer

<video oncontextmenu="return false;" controls>
    <source type="video/mp4" id="video">
</video>

现在通过JavaScript添加视频:

document.getElementById("video").src = "https://www.w3schools.com/html/mov_bbb.mp4";

功能性JSFiddle


防止右键单击的另一种方法是使用embed标记。但是,这并不提供运行视频的控件,因此需要在JavaScript中进行设置:

<embed src="https://www.w3schools.com/html/mov_bbb.mp4"></embed>

1
投票

简答:像youtube一样加密链接,不知道如何询问youtube / google如何做到这一点。 (以防你想直截了当。)

我想向任何人指出这是可能的,因为youtube做到了,如果他们可以这样做任何其他网站,它不是来自浏览器,因为我在几个浏览器上测试它,如微软边缘和Internet Explorer和所以有一种方法可以禁用它,并看到人们仍然这么说......我试图寻找答案,因为如果youtube可以而不是必须有一种方式,唯一的方法来看看他们是如何做到的,如果有人调查我正在做的youtube的脚本。我还检查了它是否是一个自定义上下文菜单,这不是因为上下文菜单过度流过inspect元素,我的意思是它已经过了它我看了,它从来没有创建一个新的类,它也用javascript实际访问inspect元素是不可能的,所以它不可能。你可以告诉它什么时候双击右键点击一个youtube视频,它会弹出chrome的上下文菜单。除此之外... youtube不会添加该功能。我正在研究并查看youtube的来源,所以如果我找到答案,我会回来的...如果有人说你不能,那么他们没有'像我一样做研究。下载YouTube视频的唯一方法是通过视频下载。

好的...我做了研究,我的研究保持你可以禁用它,除了没有javascript到它...你必须能够加密视频的链接,你可以禁用它,因为我认为任何浏览器不会显示它,如果它找不到它,当我打开一个youtube视频链接,它显示为这个“blob:https://www.youtube.com/e5c4808e-297e-451f-80da-3e838caa1275”没有引号所以它加密它所以它无法保存...你需要知道PHP对于那个,但就像你选择的答案更难,youtube使它成为最重的加密它,你需要成为一个先进的PHP程序员,但如果你不知道这一点,而不是把你选择的人作为最佳答案让它很难下载...但是如果你知道php而不是加密视频链接所以它只能在你的上面阅读...我不知道如何解释他们是如何做的但是他们做到了那里不在。 youtube加密那里视频的方式是非常聪明的,所以如果你想知道如何,而不仅仅是问你如何做到这一点...你希望这对你有帮助,尽管你已经选择了最佳答案。因此,加密链接最好是短期内。


0
投票

看起来像通过websocket流式传输视频是一个可行的选择,就像在流中框架并在画布上绘制它们一样。

Video streaming over websockets using JavaScript

我认为这将提供另一级别的保护,使客户更难以获取视频,当然通过“将视频另存为...”右键单击上下文菜单选项解决您的问题(矫枉过正?!)。


0
投票

这是我做的:

function noRightClick() {
      alert("You cannot save this video for copyright reasons. Sorry about that.");
}
    <body oncontextmenu="noRightClick();">
    <video>
    <source src="http://calumchilds.com/videos/big_buck_bunny.mp4" type="video/mp4">
    </video>
    </body>
This also works for images, text and pretty much anything. However, you can still access the "Inspect" and the "View source" tool through keyboard shortcuts. (As the answer at the top says, you can't stop it entirely.) But you can try to put barriers up to stop them.

0
投票

我们可以通过隐藏上下文菜单来实现这一点,如下所示:

<video oncontextmenu="return false;"  controls>
  <source src="https://yoursite.com/yourvideo.mp4" >
</video>

-1
投票

@ Clayton-Graul有我想要的东西,除了我需要使用AngularJS的网站的CoffeeScript版本。万一你也需要它,这就是你在AngularJS控制器中放置的内容:

    # This is how to we do JQuery ready() dom stuff
    $ ->
        # let's hide those annoying download video options.
        # of course anyone who knows how can still download
        # the video, but hey... more power to 'em.
        $('#my-video').bind 'contextmenu', -> 
            false

“奇怪的事情正在圆圈k”(这是真的)


108
投票

对于那些希望简单地从html5视频中删除右键“保存”选项的人来说,这是一个简单的解决方案

$(document).ready(function(){
   $('#videoElementID').bind('contextmenu',function() { return false; });
});

34
投票

简单回答,

你不能

如果他们正在观看您的视频,他们已经拥有了

你可以放慢速度,但不能阻止它们。


25
投票

Yes, you can do this in three steps:


  1. 将要保护的文件放在运行代码的目录的子目录中。 www.foo.com/player.html www.foo.com/videos/video.mp4
  2. 将文件保存在名为“.htaccess”的子目录中,并添加以下行。 www.foo.com/videos/.htaccess #Contents of .htaccess RewriteEngine on RewriteCond %{HTTP_REFERER} !^http://foo.com/.*$ [NC] RewriteCond %{HTTP_REFERER} !^http://www.foo.com/.*$ [NC] RewriteRule .(mp4|mp3|avi)$ - [F]

现在源链接是无用的,但我们仍然需要确保任何试图下载文件的用户都无法直接为该文件提供服务。

  1. 对于更完整的解决方案,现在使用Flash播放器(或html画布)提供视频,而不是直接链接到视频。要删除右键菜单,请添加到您的HTML: <body oncontextmenu="return false;">

结果:

www.foo.com/player.html将正确播放视频,但如果您访问www.foo.com/videos/video.mp4:

错误代码403:FORBIDDEN

这将适用于直接下载,cURL,热链接,您可以命名。

这是对所提出的两个问题的完整答案,而不是问题的答案:“我可以阻止用户下载他们已下载的视频吗?”


22
投票

我通常使用的最好的方法很简单,我完全禁用整个页面中的上下文菜单,纯html + javascript:

 <body oncontextmenu="return false;">

而已!我之所以这样做,是因为您可以通过右键单击来查看源代码。 好吧,你说:“我可以直接使用浏览器视图源”,这是真的,但我们从你不能停止下载html5视频的事实开始。


12
投票

作为客户端开发人员,我建议使用blob URL,blob URL是一个客户端URL,它引用二进制对象

<video id="id" width="320" height="240"  type='video/mp4' controls  > </video>

在HTML中将您的视频src留空,并在JS中使用AJAX获取视频文件,确保响应类型为blob

window.onload = function() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'mov_bbb.mp4', true);
    xhr.responseType = 'blob'; //important
    xhr.onload = function(e) {
        if (this.status == 200) {
            console.log("loaded");
            var blob = this.response;
            var video = document.getElementById('id');
            video.oncanplaythrough = function() {
                console.log("Can play through video without stopping");
                URL.revokeObjectURL(this.src);
            };
            video.src = URL.createObjectURL(blob);
            video.load();
        }
    };
    xhr.send();
}

注意:建议不要对大文件使用此方法

编辑

  • 使用跨源阻止来避免直接下载
  • 如果视频是通过API传递的,请使用不同的方法(PUT / POST)而不是'GET'

10
投票

PHP将html5视频标记与一个会话一起发送,其中密钥是随机字符串,值是文件名。

ini_set('session.use_cookies',1);
session_start();
$ogv=uniqid(); 
$_SESSION[$ogv]='myVideo.ogv';
$webm=uniqid(); 
$_SESSION[$webm]='myVideo.webm';
echo '<video autoplay="autoplay">'
    .'<source src="video.php?video='.$ogv.' type="video/ogg">'
    .'<source src="video.php?video='.$webm.' type="video/webm">'
    .'</video>'; 

现在要求PHP发送视频。 PHP恢复文件名;删除会话并立即发送视频。此外,必须存在所有“无缓存”和mime类型标头。

ini_set('session.use_cookies',1);
session_start();
$file='myhiddenvideos/'.$_SESSION[$_GET['video']];
$_SESSION=array();
$params = session_get_cookie_params();
setcookie(session_name(),'', time()-42000,$params["path"],$params["domain"],
                                         $params["secure"], $params["httponly"]);
if(!file_exists($file) or $file==='' or !is_readable($file)){
  header('HTTP/1.1 404 File not found',true);
  exit;
  }
readfile($file);
exit:

现在,如果用户在新标签中复制网址或使用上下文菜单,他将没有运气。


5
投票

您至少可以阻止非技术人员使用右键单击上下文菜单下载您的视频。您可以使用oncontextmenu属性禁用任何元素的上下文菜单。

oncontextmenu="return false;"

这适用于body元素(整个页面)或仅在视频标记内使用它的单个视频。

<video oncontextmenu="return false;" controls>...</video>

4
投票

我们最终将AWS CloudFront与过期的URL结合使用。视频将加载,但是当用户右键单击并选择另存为时,他们最初收到的视频网址已过期。搜索CloudFront Origin Access Identity。

生成视频网址需要一个密钥对,可以在AWS CLI中创建。仅供参考,这不是我的代码,但效果很好!

$resource = 'http://cdn.yourwebsite.com/videos/yourvideourl.mp4';
$timeout = 4;

//This comes from key pair you generated for cloudfront
$keyPairId = "AKAJSDHFKASWERASDF";

$expires = time() + $timeout; //Time out in seconds
$json = '{"Statement":[{"Resource":"'.$resource.'","Condition" {"DateLessThan":{"AWS:EpochTime":'.$expires.'}}}]}';     

//Read Cloudfront Private Key Pair
$fp=fopen("/absolute/path/to/your/cloudfront_privatekey.pem","r"); 
$priv_key=fread($fp,8192); 
fclose($fp); 

//Create the private key
$key = openssl_get_privatekey($priv_key);
if(!$key)
{
    echo "<p>Failed to load private key!</p>";
    return;
}

//Sign the policy with the private key
if(!openssl_sign($json, $signed_policy, $key, OPENSSL_ALGO_SHA1))
{
    echo '<p>Failed to sign policy: '.openssl_error_string().'</p>';
    return;
}

//Create url safe signed policy
$base64_signed_policy = base64_encode($signed_policy);
$signature = str_replace(array('+','=','/'), array('-','_','~'), $base64_signed_policy);

//Construct the URL
$url = $resource.'?Expires='.$expires.'&Signature='.$signature.'&Key-Pair-Id='.$keyPairId;

return '<div class="videowrapper" ><video autoplay controls style="width:100%!important;height:auto!important;"><source src="'.$url.'" type="video/mp4">Your browser does not support the video tag.</video></div>';
© www.soinside.com 2019 - 2024. All rights reserved.