代码之家  ›  专栏  ›  技术社区  ›  Dan Kohn

根据你是否在中国,在优酷和YouTube之间切换

  •  15
  • Dan Kohn  · 技术社区  · 7 年前

    我正在主持一个会议网站,我想在那里嵌入优酷视频(如果你在中国)和YouTube视频。会议网站通过防火墙内的cdn提供服务。我得到了下面的代码来在优酷的内部版本和外部版本之间切换。

    不幸的是,ipinfo.io在防火墙内部似乎无法访问,因此代码在10秒后超时。

    我已经考虑过在默认情况下重写页面以使用优酷视频,编写一个小的、非阻塞的javascript函数,尝试访问YouTube。如果可以的话,用youtube代替youku。如果不行,就安全地离开。这样,YouTube的可访问性就成了关键测试,而不是你是否在中国。

    另外,我也考虑在我的网站上托管视频,这样它就可以通过防火墙内的cdn进行复制。但是,这意味着即使您的连接速度很慢,视频也将始终以完全分辨率下载。

    关于如何在优酷和YouTube之间切换,有什么更好的建议吗?或者更普遍地说,在中国国内外都可以播放视频?

    jQuery.get("https://ipinfo.io", function(response) {
        var country = response.country;
    
        if(country == 'CN') {
            youku.attr('src',chinaVideo)
        } else {
            youku.attr('src',generalVideo)
        }
    }, "jsonp");
    
    7 回复  |  直到 7 年前
        1
  •  6
  •   Bharata colxi    7 年前

    下面是我们要使用的javascript:

    $(document).ready(function (){
        var country = '',
        youku = $('#youku');
    
        $.ajax({
            url: "https://ipinfo.io",
            dataType: "jsonp",
            success: function(response){
                var country = response.country;
    
                if(country != 'CN') {
                    youku.attr('src','https://www.youtube.com/embed/K3cEE5h7c1s')
                }
             },
             error: function(){
                console.log('sorry...')
             },
             timeout: 5000
        });     
    });
    

    我们将优酷链接包含在HTML中,如果国家不是中国,我们将切换到YouTube。如果连接到 ipinfo.io 超时,这在中国有时会发生。

    编辑:修改为添加5秒超时。

        2
  •  3
  •   Munim Munna    7 年前

    最好是专门检查YouTube是否在用户的网络中被屏蔽,而不是基于永远不100%可靠的IP过滤出国家。这样,它甚至可以在任何学校/办公室环境中工作,在这种环境下,网络管理员可以出于任何原因阻止YouTube。

    This 这是我能找到的最好的答案,它试图加载 favicon 通过javascript的YouTube。如果下载成功,YouTube就可以访问。这个图片只有0.2千字节的下载量,很可能已经被任何访问过YouTube的用户缓存了。

    这意味着,对于拥有YouTube访问权限的用户来说,结果几乎是即时的,对于防火墙被阻止的用户来说,结果需要几秒钟的时间。代码很简单:

    jQuery(function(){
        var youku = jQuery('#youku');
        var image = new Image();
        image.onload = function(){
            youku.attr('src','https://www.youtube.com/embed/K3cEE5h7c1s')
        };
        image.onerror = function(){
            youku.attr('src','https://www.youku.com/embed/K3cEE5h7c1s')
        };
        image.src = "https://youtube.com/favicon.ico";
    });
    

    这是一个比上述更好的解决方案,因为它不等待 document.ready jquery事件,图像立即开始加载。

    (function(){
        var image = new Image();
        image.onload = function(){
            jQuery(function(){
                jQuery('#youku').attr('src','https://www.youtube.com/embed/K3cEE5h7c1s')
            });
        };
        image.onerror = function(){
            jQuery(function(){
                jQuery('#youku').attr('src','https://www.youku.com/embed/K3cEE5h7c1s')
            });
        };
        image.src = "https://youtube.com/favicon.ico";
    })();
    

    根据评论更新:

    如果有可能图像以前缓存在用户的计算机上,则将当前时间戳参数添加到图像URL将确保加载图像,而不必考虑以前缓存的图像。

        image.src = "https://youtube.com/favicon.ico?_=" + Date.now();
    
        3
  •  0
  •   223seneca    7 年前

    您当前的解决方案并不理想,因为它取决于get请求超时,这将减慢速度。因为这个问题主要围绕 ipinfo.io 由于在中国被屏蔽,一个有效的解决方案很可能涉及一个基于中国的IP识别服务。

    尝试使用 http://www.ip138.com/ . 谷歌翻译的效果很好,可以用英语阅读。似乎没有正式的JSON API,但您可以点击 http://www.ip138.com/ips138.asp?ip=<IP_ADDRESS_HERE> 并获取位置信息。

    为此,使用jquery(因为您已经在使用它)将dom导航到 本站数据: 在国家名称之前。我认为当前构造的页面的选择器只是 $( "li" ).first() . 提取冒号后的字符串,并将其发布到Google Translate API,以获得英文和voila的国家名称!你有一个更快更可靠(如果相当复杂)的方式来看看游客是否在中国。

    编辑:不完全清楚您是否事先拥有用户的IP地址。如果没有,可以使用类似的方法 https://geoiptool.com/zh/ 也位于中国境内,因此不会被封锁。我很乐意根据需要把这部分充实起来。

        4
  •  0
  •   amankkg    7 年前

    关于如何在优酷和YouTube之间切换的更好建议,或者 更普遍的是,中国国内外都有可播放的视频?

    我建议你看看阿里云。他们有很多服务,但是阿法克没有免费的计划。
    因为我不熟悉中国的其他云提供商,让我描述一下阿里云的解决方案。

    我看到两种可能的选择:

    1. 使用他们的 内容传递服务 创建两个JS包——一个面向中国,另一个面向世界。第一个将嵌入优酷的视频,第二个将嵌入YouTube的视频。上传到cdn后,您可以强制将其推送到中国/世界的本地节点,从而始终为用户提供快速、最新的响应;
    2. 使用他们的 媒体转码服务 用于视频处理+ 对象存储服务 用于视频托管+ 内容传递服务 用于分发。通过这种方式,您可以创建多个不同质量的视频,并将其分发到用户附近。JS将直接嵌入来自cdn的视频。对于一个视频来说,这可能是一个过度杀戮。
        5
  •  0
  •   eddies    7 年前

    使用客户端的时区怎么样?虽然不完美,但它可以让您避免完全依赖超时或任何geoip服务请求。如果可能的话,我会避免使用可能导致同一地址块(例如来自会议与会者)对同一阻塞资源进行多次重复调用的方法。当我最后一次在中国生活的时候,我记得我触发了来自防火墙的TCP重置,这将持续30秒或更长时间。

    Intl.DateTimeFormat().resolvedOptions().timeZone 是合理的 well-supported 在现代浏览器中。在中国,应返回中国的IANA时区:“亚洲/上海”:

    console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)

    还有图书馆( jsTimezoneDetect moment-timezone )将上述内容与 getTimezoneOffset 功能 Date 跨越多个时间点,对时区进行有根据的猜测,这可能会在旧浏览器中产生更好的结果:

    console.log(jstz.determine().name());
    console.log(moment.tz.guess());
    <script src="//cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.6/jstz.min.js"></script>
    
    <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.5/moment-timezone-with-data-2010-2020.min.js"></script>

    对于我来说,我可能会尝试将时区检测为“亚洲/上海”,并返回到“UTC+8”的时区偏移量(仅时区偏移量就可以捕获比中国大陆更多的数据,但我认为这是一个可接受的回退策略的过度扩展),例如:

    var ianaTz = Intl.DateTimeFormat().resolvedOptions().timeZone;
    var offset = new Date().getTimezoneOffset();
    
    if (ianaTz === "Asia/Shanghai" || (ianaTz == null && offset/60 == -8)) {
      console.log("We'll assume China");
    } else {
      console.log("not China");
    }
        6
  •  0
  •   Cambesa    7 年前

    您可以使用ffmpeg将视频转换为HLS版本,根据RFC8216手工制作HLS播放列表(.m3u8)。ffmpeg不会为您创建主播放列表。HLS有助于根据互联网速度调整分辨率。如果你把它和免费的hls.js javascript媒体播放器结合在一起,你可以把它放在你自己的网站上,以便通过中国的防火墙,支持自适应分辨率。

    下面是一个HLS主播放列表示例,因此您不必读取RFC 8216,该文件将称为video.m3u8:

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080
    Video_1080p.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=9000000,RESOLUTION=2560x1440
    Video_1440p.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=16000000,RESOLUTION=3840x2160
    Video_4k.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=2800000,RESOLUTION=1280x720
    Video_720p.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=1400000,RESOLUTION=842x480
    Video_480p.m3u8
    #EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360
    Video_360p.m3u8
    

    带宽是以每秒位为单位指定的,质量顺序并不重要,因为MediaPlayer选择要播放的分辨率。

    在命令提示符中可用于ffmpeg的命令是:

    ffmpeg -hwaccel dxva2 -hide_banner -y -i "C:\input\Video.mp4" -vf scale=1920:1080 -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -r 30 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 2 -hls_playlist_type vod -b:v 5000k -maxrate 5350k -bufsize 7500k -b:a 192k -hls_segment_filename "C:\output\Video_1080p_%03d.ts" "C:\output\Video_1080p.m3u8" -vf scale=2560:1440 -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -r 30 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 2 -hls_playlist_type vod -b:v 9000k -maxrate 10350k -bufsize 14500k -b:a 192k -hls_segment_filename "C:\output\Video_1440p_%03d.ts" "C:\output\Video_1440p.m3u8" -vf scale=3840:2160 -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -r 30 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 2 -hls_playlist_type vod -b:v 16000k -maxrate 20350k -bufsize 26000k -b:a 192k -hls_segment_filename "C:\output\Video_4k_%03d.ts" "C:\output\Video_4k.m3u8" -vf scale=1280:720 -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -r 30 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 2 -hls_playlist_type vod -b:v 2800k -maxrate 2996k -bufsize 4200k -b:a 128k -hls_segment_filename "C:\output\Video_720p_%03d.ts" "C:\output\Video_720p.m3u8" -vf scale=842:480 -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -r 30 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 2 -hls_playlist_type vod -b:v 1400k -maxrate 1498k -bufsize 2100k -b:a 128k -hls_segment_filename "C:\output\Video_480p_%03d.ts" "C:\output\Video_480p.m3u8" -vf scale=640:360 -c:a aac -ar 48000 -c:v h264 -profile:v main -crf 20 -r 30 -sc_threshold 0 -g 48 -keyint_min 48 -hls_time 2 -hls_playlist_type vod -b:v 800k -maxrate 865k -bufsize 1200k -b:a 96k -hls_segment_filename "C:\output\Video_360p_%03d.ts" "C:\output\Video_360p.m3u8"
    

    唯一需要做的就是用视频替换c:\input\video.mp4,并用视频的输出名称替换所有c:\output\video。360p代表输出视频文件名中指定的分辨率,它不影响实际分辨率,%03d是一个命令,它被解析为给视频片段一个数字,如001到999。下划线用于可读性。

    评论说明: -hwaccel dxva2意味着ffmpeg将使用DirectX进行硬件加速,这可以从Windows Vista和更高版本获得。 -hls_time 2将碎片时间设置为每个碎片2秒。 AAC和H264是用于HLS视频片段的编解码器。

    此ffmpeg命令生成6个质量级别,但不创建主播放列表。主播放列表是一个按带宽播放列表的播放列表(见上文),取决于HLS播放器选择播放视频片段的播放列表的互联网速度。

        7
  •  0
  •   Diego Perini    7 年前

    使用javascript从浏览器获取区域设置信息

    要加快检测过程,您可以首先尝试从浏览器包安装语言中提取区域设置信息:

    navigator.language
    navigator.languages
    

    然后将其结合起来,或者作为最后一个资源,回退到地理位置或其他方法,从 Accept-Language HTTP头。

    以下是获取浏览器头的外部服务示例:

    https://ajaxhttpheaders1.appspot.com/?callback=getHeaders
    

    另一个可能与上述解决方案结合的路径是从用户环境或浏览上下文(window.location、document.cookie、document.localstorage、date()或date().tolocalString()et similar)中获取一些字符串,并使用正则表达式unicode范围扫描这些字符串以获得中文unicode码点。

    我相信这会让你得到一个非常好的近似值,而不会提出额外的要求。作为我的火狐浏览器的一个例子,一个调用 Date().toLocaleString() 生产:

    "Mon Jul 30 2018 01:35:38 GMT+0200 (Ora legale dell’Europa centrale)"
    

    可以很容易地将其解析为“意大利语”区域设置。

    在某个地方,你会发现一个汉字/符号的Unicode点。

    推荐文章