Spaces:
Running
Running
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<link rel="preconnect" href="https://rsms.me/"> | |
<link rel="stylesheet" href="https://rsms.me/inter/inter.css"> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/daydreamer-json/SomeFontRepo@main/somefontrepo.css"> | |
<link rel="preconnect" href="https://fonts.googleapis.com"> | |
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet"> | |
<link rel="stylesheet prefetch" href="https://daydreamer-json-me.static.hf.space/apple_fonts.css"> | |
<link rel="stylesheet" href="https://cdn.vidstack.io/player/theme.css"> | |
<link rel="stylesheet" href="https://cdn.vidstack.io/player/video.css"> | |
<script src="https://cdn.vidstack.io/player" type="module"></script> | |
<script src='https://unpkg.com/bignumber.js'></script> | |
<script src='https://unpkg.com/cbor-web'></script> | |
<style> | |
:root { font-family: 'Inter', sans-serif; } | |
@supports (font-variation-settings: normal) { | |
:root { font-family: 'Inter var', sans-serif; } | |
} | |
body { | |
margin: 0; | |
background-color: #000000; | |
width: 100vw; | |
height: 100vh; | |
font-family: 'SF Pro Text', 'Inter', 'Noto Sans JP', sans-serif; | |
} | |
.wrapper { | |
height: 100vh; | |
display: flex; | |
flex-direction: column; | |
} | |
#player { | |
flex-grow: 1; | |
top: 0; | |
left: 0; | |
height: 100%; | |
width: 100%; | |
font-family: 'SF Pro Text', 'Inter', 'Noto Sans JP', sans-serif; | |
overflow: hidden; | |
} | |
.vds-video-layout { | |
--video-font-family: 'Inter', 'Noto Sans JP', sans-serif ; | |
--video-border-radius: 0px ; | |
--video-border: 0px ; | |
} | |
:where([data-media-provider], video, media-poster) { | |
border-radius: var(--video-border-radius); | |
border: var(--video-border); | |
} | |
:where([data-media-player][data-view-type=video]:not([data-fullscreen])) { | |
border-radius: var(--video-border-radius); | |
border: var(--video-border); | |
} | |
:where([data-media-player][data-view-type=video]) { | |
border-radius: var(--video-border-radius); | |
border: var(--video-border); | |
} | |
[data-media-provider] video { | |
width: 100%; | |
height: 100%; | |
object-fit: contain; | |
} | |
media-captions { | |
/* font-family: 'SDK_JP_Web', sans-serif; */ | |
font-family: 'Inter', 'Noto Sans JP', sans-serif; | |
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75), -1px 1px 0 rgba(0, 0, 0, 0.75), 1px -1px 0 rgba(0, 0, 0, 0.75), -1px -1px 0 rgba(0, 0, 0, 0.75); | |
} | |
footer.copyrightDisp { | |
position: fixed; | |
left: 0; | |
bottom: 0; | |
padding: 0; | |
margin: 0 0 10px 10px; | |
color: #ffffff80; | |
z-index: 2; | |
user-select: none; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="wrapper"> | |
<media-player | |
title="" | |
aspect-ratio="16/9" | |
crossorigin | |
id="player" | |
> | |
<media-provider id="player-media-outlet-el"> | |
</media-provider> | |
<media-audio-layout></media-audio-layout> | |
<media-video-layout></media-video-layout> | |
</media-player> | |
</div> | |
<script> | |
const uiTranslation = { | |
"ja-JP": { | |
'Caption Styles': '字幕のスタイル', | |
'Captions look like this': '字幕はこのように見えます', | |
'Closed-Captions Off': '字幕オフ', | |
'Closed-Captions On': '字幕オン', | |
'Display Background': '背景を表示', | |
'Enter Fullscreen': '全画面表示', | |
'Enter PiP': 'PiP', | |
'Exit Fullscreen': '全画面表示を終了', | |
'Exit PiP': 'PiPを終了', | |
'Google Cast': 'Google Cast', | |
'Keyboard Animations': 'キーボードアニメーション', | |
'Seek Backward': '戻る', | |
'Seek Forward': '進む', | |
'Skip To Live': 'ライブへスキップ', | |
'Text Background': 'テキストの背景', | |
Accessibility: 'アクセシビリティ', | |
AirPlay: 'AirPlay', | |
Announcements: 'アナウンス', | |
Audio: '音声', | |
Auto: '自動', | |
Boost: 'ブースト', | |
Captions: '字幕', | |
Chapters: 'チャプター', | |
Color: '色', | |
Connected: '接続しました', | |
Connecting: '接続中', | |
Continue: '続ける', | |
Default: 'デフォルト', | |
Disabled: '無効', | |
Disconnected: '切断されました', | |
Download: 'ダウンロード', | |
Family: 'ファミリー', | |
Font: 'フォント', | |
Fullscreen: '全画面表示', | |
LIVE: 'LIVE', | |
Loop: 'ループ', | |
Mute: 'ミュート', | |
Normal: '標準', | |
Off: 'オフ', | |
Opacity: '不透明度', | |
Pause: '一時停止', | |
PiP: 'PiP', | |
Play: '再生', | |
Playback: '再生', | |
Quality: '画質', | |
Replay: 'リプレイ', | |
Reset: 'リセット', | |
Seek: 'シーク', | |
Settings: '設定', | |
Shadow: '影', | |
Size: 'サイズ', | |
Speed: '速度', | |
Text: 'テキスト', | |
Track: 'トラック', | |
Unmute: 'ミュート解除', | |
Volume: '音量', | |
} | |
}; | |
const pageUUID = "d511b8f7-5579-41a6-8450-e9f958507f94"; | |
let playerConfigObject = { | |
"volume": null, | |
"muted": null | |
}; | |
window.volumeChangeEventCounter = 0; | |
window.addEventListener('load', async function(){ | |
// const cbor = require('cbor-web'); | |
// uiTranslation.cbor.ja = atob(uiTranslation.base64.ja); | |
// uiTranslation.json.ja = await cbor.decodeFirst(uiTranslation.cbor.ja); | |
document.oncontextmenu = function () {return false;} | |
window.player = document.querySelector('media-player'); | |
for (let i = 0; i < Object.keys(uiTranslation).length; i++) { | |
if (window.navigator.language == Object.keys(uiTranslation)[i]) { | |
document.querySelector('media-video-layout').translations = uiTranslation[Object.keys(uiTranslation)[i]]; | |
} | |
} | |
const pageUrlLocationHref = new URL(location.href); | |
const pageSearchParams = pageUrlLocationHref.searchParams; | |
if (pageSearchParams.has("url") === true && pageSearchParams.get("url") !== "") { | |
attachSourceToPlayer(pageSearchParams.get("url")); | |
if (pageSearchParams.has("subtitle") === true && pageSearchParams.get("subtitle") !== "") { | |
attachSubtitleSourceToPlayer(pageSearchParams.get("subtitle")); | |
} | |
} else { | |
const promptedUrl = prompt("Please input source URL"); | |
if (promptedUrl === "") { | |
alert("Source not found"); | |
} else { | |
attachSourceToPlayer(promptedUrl); | |
} | |
} | |
player.addEventListener('provider-change', (event) => { | |
const provider = event.detail; | |
if (provider?.type === 'hls') { | |
provider.library = 'https://cdn.jsdelivr.net/npm/hls.js@1.4.12/dist/hls.min.js'; | |
provider.config = { | |
"debug": false, | |
"enableWorker": true, | |
"lowLatencyMode": true, | |
"backBufferLength": 90 | |
}; | |
window.provider = provider; | |
} | |
}); | |
importConfigFromBrowser(); | |
player.addEventListener('volume-change', (event) => { | |
volumeChangeSaveToConfig(); | |
}); | |
const { audioTracks } = player.state; | |
player.subscribe(({ audioTracks }) => { | |
mhyLangAutoSelect(JSON.stringify(audioTracks, '', ' ')); | |
}); | |
}); | |
function attachSourceToPlayer (url) { | |
player.src = url; | |
player.title = url.match(/^(?:[^:\/?#]+:)?(?:\/\/[^\/?#]*)?(?:([^?#]*\/)([^\/?#]*))?(\?[^#]*)?(?:#.*)?$/)[2].match(/^(.+?)(\.[^.]+)?$/)[1]; | |
} | |
function attachSubtitleSourceToPlayer (url) { | |
const outletElement = document.querySelector('#player-media-outlet-el'); | |
const trackElement = document.createElement("track"); | |
trackElement.src = url; | |
trackElement.kind = "subtitles"; | |
trackElement.label = "Subtitle"; | |
outletElement.appendChild(trackElement); | |
} | |
function volumeChangeSaveToConfig () { | |
if (volumeChangeEventCounter >= 0) { | |
playerConfigObject.volume = player.volume; | |
playerConfigObject.muted = player.muted; | |
saveConfigToBrowser(); | |
} | |
volumeChangeEventCounter += 1; | |
} | |
function importConfigFromBrowser () { | |
if (window.localStorage && localStorage.getItem(`${pageUUID}`) !== null) { | |
playerConfigObject = JSON.parse(localStorage.getItem(`${pageUUID}`)); | |
player.volume = playerConfigObject.volume; | |
player.muted = playerConfigObject.muted; | |
console.warn(`Loaded config from localStorage\n${pageUUID} = ${JSON.stringify(playerConfigObject, '', ' ')}`); | |
} | |
} | |
function saveConfigToBrowser () { | |
if (window.localStorage) { | |
localStorage.setItem(`${pageUUID}`, JSON.stringify(playerConfigObject)); | |
console.warn(`Saved config to localStorage\n${pageUUID} = ${JSON.stringify(playerConfigObject, '', ' ')}`); | |
} | |
} | |
function mhyLangAutoSelect (audioTracks) { | |
const testBefore = [ | |
{ | |
"id": "0", | |
"label": "Chinese", | |
"language": "zh-CN", | |
"kind": "main" | |
}, | |
{ | |
"id": "1", | |
"label": "English", | |
"language": "en-US", | |
"kind": "main" | |
}, | |
{ | |
"id": "2", | |
"label": "Japanese", | |
"language": "ja-JP", | |
"kind": "main" | |
}, | |
{ | |
"id": "3", | |
"label": "Korean", | |
"language": "ko-KR", | |
"kind": "main" | |
} | |
]; | |
if (audioTracks === JSON.stringify(testBefore, '', ' ')) { | |
for (let i = 0; i < testBefore.length; i++) { | |
if (window.navigator.language.slice(0,2) === testBefore[i].language.slice(0,2)) { | |
player.audioTracks[i].selected = true; | |
console.warn(`Player audio language has been automatically changed to\n${JSON.stringify(player.audioTracks[i], '', ' ')}`); | |
} | |
} | |
} | |
} | |
</script> | |
</body> | |
</html> |