私は、中国にいる場合はYoukuビデオを埋め込み、それ以外の場合はYouTubeビデオを埋め込みたい会議Webサイトをホストしています。会議のWebサイトは、グレートファイアウォール内のCDNを介して提供されています。 Youkuの内部バージョンと外部バージョンを切り替えるために、以下のコードが提供されました。
残念ながら、ipinfo.ioはグレートファイアウォール内でアクセスできないようであるため、コードは10秒後にタイムアウトします。
デフォルトでYoukuビデオを使用するようにページを書き直し、YouTubeに到達しようとする小さな非ブロッキングJavaScript関数を作成することを検討しました。可能であれば、YoukuをYouTubeに置き換えてください。それができない場合は、無害に終了します。そうすれば、あなたが中国にいるかどうかではなく、YouTubeの到達可能性が重要なテストになります。
または、自分のサイトでビデオをホストして、グレートファイアウォール内のCDNを介して複製されるようにすることを考えました。ただし、接続速度が遅い場合でも、ビデオは常にフル解像度でダウンロードされます。
Youkuと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");
これが私たちが使用している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にYoukuリンクを含め、国が中国でない場合はYouTubeに切り替えます。これは、ipinfo.io
への接続がタイムアウトした場合でも機能します。これは、中国で発生することがあります。
編集:5秒のタイムアウトを追加するように改訂。
Edit2:これをオープンソースとして実装しましたWordpressプラグイン、他の人が興味を持っている場合に備えて。 https://github.com/cncf/china-video-block
100%信頼できるとは限らないIPに基づいて国を除外するのではなく、ユーザーのネットワークでYouTubeがブロックされているかどうかを具体的に確認することをお勧めします。このようにして、YouTubeが何らかの理由でネットワーク管理者によってブロックされる可能性のある学校/オフィス環境でも機能します。
This は、JavaScriptを介してYouTubeのfavicon
を読み込もうとするこの点で私が見つけた最良の答えです。その小さな画像のダウンロードに成功すると、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";
});
これは、jQueryのdocument.ready
イベントを待たず、画像の読み込みがすぐに開始されるため、上記よりも優れたソリューションです。
(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();
YoukuとYoutubeを切り替える方法、またはより一般的には中国の内外でビデオを再生できるようにする方法について、より良い提案はありますか?
私はAlibabaCloudを見てみることをお勧めします。彼らはたくさんのサービスを持っていますが、AFAIKには無料のプランはありません。
私は中国の他のクラウドプロバイダーに精通していないので、AlibabaCloudのソリューションについて説明します。
私はあなたのために2つの可能なオプションを見ます:
Ffmpegを使用してビデオをHLSバージョンに変換し、RFC 8216に基づいて手動でHLSプレイリスト(.m3u8)を作成できます。ffmpegはマスタープレイリストを作成しません。 HLSは、解像度をインターネット速度に適合させるのに役立ちます。これを無料のhls.jsjavascriptメディアプレーヤーと組み合わせると、中国の優れたファイアウォールを通過し、適応型解像度をサポートするために、独自のサイトでホストできます。
これはHLSマスタープレイリストの例です。RFC8216を読む必要はありません。ファイルの名前は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
帯域幅はビット/秒で指定されます。メディアプレーヤーが再生する解像度を選択するため、品質の順序は重要ではありません。
コマンドプロンプトで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を使用したハードウェアアクセラレーションを使用することを意味します。これは、WindowsVista以降で利用できます。 -hls_time 2は、フラグメント時間をフラグメントごとに2秒に設定します。 aacとh264は、hlsビデオフラグメントで使用するコーデックです。
Ffmpegのこのコマンドは、6つの品質レベルを生成しますが、マスタープレイリストは作成しません。マスタープレイリストは、インターネットの速度に応じて、帯域幅ごとのプレイリスト(上記を参照)を持つプレイリストであり、hlsプレーヤーは再生するビデオフラグメントのプレイリストを選択します。
現在のソリューションは、GETリクエストのタイムアウトに依存しているため、理想的ではありません。これにより、処理速度が低下します。この問題は主に中国での_ipinfo.io
_のブロックを中心に展開しているため、効果的な解決策には中国に拠点を置くIP識別サービスが含まれる可能性があります。
_http://www.ip138.com/
_を使用してみてください。グーグル翻訳は英語でそれを読むのに十分うまく機能します。正式なJSONAPIはないようですが、_http://www.ip138.com/ips138.asp?ip=<IP_ADDRESS_HERE>
_を押して位置情報を取得できます。
これを行うには、jQueryを使用してDOMをナビゲートし(すでに使用しているため)、国の名前の前にある_本站数据:
_の行に移動します。現在ページが作成されているので、そのセレクターは単に$( "li" ).first()
だと思います。コロンの後に文字列を抽出し、POSTそれをGoogle翻訳APIに送信して、英語と出来上がりで国名を取得します。より速く、より信頼性の高い(かなり複雑な場合)方法で確認できます。訪問者が中国にいるかどうか。
編集:事前にユーザーのIPアドレスを持っているかどうかは完全には明らかではありません。そうでない場合は、_https://geoiptool.com/zh/
_で同様の方法を使用できます。これも中国に拠点を置いているため、ブロックされていません。必要に応じてこの部分を肉付けできてうれしいです。
クライアントのタイムゾーンを使用するのはどうですか?完璧ではありませんが、タイムアウトやgeoipサービスリクエストに完全に依存することを回避できます。可能であれば、同じアドレスブロック(会議の参加者など)から同じブロックされたリソースへの呼び出しが何度も繰り返される可能性のあるアプローチは避けます。私が最後に中国に住んでいたとき、グレートファイアウォールからTCPリセットをトリガーしたことを覚えています。これは30秒以上続きます。
Intl.DateTimeFormat().resolvedOptions().timeZone
は、最近のブラウザでは合理的に 十分にサポートされています です。中国では、中国のIANAタイムゾーンを返す必要があります:「アジア/上海」:
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)
上記とgetTimezoneOffset
のDate
関数を複数のポイントで組み合わせたライブラリ( jsTimezoneDetect および moment-timezone )もあります。時間、タイムゾーンの知識に基づいた推測を行うため。これにより、古いブラウザでより良い結果が得られる可能性があります。
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");
}
検出プロセスを高速化するには、最初にブラウザパッケージのインストール言語からロケール情報を抽出してみます。
_navigator.language
navigator.languages
_
次に、それを組み合わせるか、最後のリソースとして、地理的な場所またはその他の手段にフォールバックして、_Accept-Language
_ HTTPヘッダーからユーザーの言語設定を検出します。
以下は、ブラウザのヘッダーを取得するための外部サービスの例です。
_https://ajaxhttpheaders1.appspot.com/?callback=getHeaders
_
上記の解決策と組み合わせることができる別のパスは、ユーザー環境またはブラウジングコンテキスト(window.location、document.cookie、document.localStorage、Date()またはDate()。toLocaleString()など)から文字列を取得することです。正規表現のUnicode範囲を使用して、これらの文字列をスキャンして中国語のUnicodeコードポイントを探します。
これにより、追加のリクエストを行わなくても、非常に適切な概算が得られると思います。私のFirefoxブラウザの例として、Date().toLocaleString()
を呼び出すと次のようになります。
_"Mon Jul 30 2018 01:35:38 GMT+0200 (Ora legale Dell’Europa centrale)"
_
これは、「イタリア語」ロケールとして簡単に解析できます。
どこかに、中国の表意文字/記号のUnicodeポイントがあります。