mirror of
https://github.com/seigler/HLS-over-IPFS-video-player
synced 2025-07-26 01:06:15 +00:00
feat: context menu, link to current time
This commit is contained in:
parent
38d372a603
commit
1b49b532dc
3 changed files with 107 additions and 38 deletions
|
@ -7,6 +7,7 @@ Accepts three query parameters:
|
|||
- `hash`: required. The IPFS hash of a folder containing an HLS playlist and its files.
|
||||
- `source`: optional, defaults to `master.m3u8`.
|
||||
- `title`: optional, allows overriding the browser tab title.
|
||||
- `time`: optional, start video at this many seconds
|
||||
|
||||
## Usage Examples:
|
||||
|
||||
|
|
34
index.html
34
index.html
|
@ -55,13 +55,44 @@
|
|||
padding: 0.5em;
|
||||
overflow: auto;
|
||||
}
|
||||
#contextMenu {
|
||||
position: sticky;
|
||||
background-color: #2f2f2faf;
|
||||
color: white;
|
||||
width: 20em;
|
||||
}
|
||||
#contextMenu > div {
|
||||
border: 1px solid #0000007f;
|
||||
cursor: pointer;
|
||||
padding: 0.5em;
|
||||
}
|
||||
#contextMenu > div + div {
|
||||
border-top: none;
|
||||
}
|
||||
#contextBackground {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="module" defer="" src="./src/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<video id="video" controls="" autoplay=""></video>
|
||||
<video id="video" controls="" controlsList="nodownload" autoplay=""></video>
|
||||
<div id="status"></div>
|
||||
</div>
|
||||
<div class="is-hidden" id="contextBackground">
|
||||
<div id="contextMenu">
|
||||
<div id="contextMenu-url">Copy video URL</div>
|
||||
<div id="contextMenu-urlWithTime">Copy video URL at current time</div>
|
||||
</div>
|
||||
</div>
|
||||
<section id="help">
|
||||
<h1>HLS over IPFS video player</h1>
|
||||
<h2 id="how-to-use">
|
||||
|
@ -79,6 +110,7 @@
|
|||
<li>
|
||||
<code>title</code>: optional, allows overriding the browser tab title.
|
||||
</li>
|
||||
<li><code>time</code>: optional, start the video at this many seconds</li>
|
||||
</ul>
|
||||
<h2 id="usage-examples">
|
||||
<a class="anchor" href="#usage-examples"></a>Usage Examples:
|
||||
|
|
110
src/index.js
110
src/index.js
|
@ -4,7 +4,77 @@ import { create } from 'ipfs-core'
|
|||
import Hls from 'hls.js'
|
||||
import HlsjsIpfsLoader from 'hlsjs-ipfs-loader'
|
||||
|
||||
let node
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
setBodyHeight()
|
||||
window.addEventListener('resize', setBodyHeight)
|
||||
const hash = getUrlParameter('hash')
|
||||
const source = getUrlParameter('source')
|
||||
const title = getUrlParameter('title')
|
||||
const time = getUrlParameter('time')
|
||||
setUpContextMenu() // todo move back inside if(hash)
|
||||
if (title) {
|
||||
document.title = title
|
||||
}
|
||||
if (hash) {
|
||||
document.getElementById('help').style.display = 'none'
|
||||
const video = document.getElementById('video')
|
||||
video.style.display = 'block'
|
||||
const repoPath = 'ipfs-' + Math.random()
|
||||
showStatus('Connecting to IPFS')
|
||||
const node = await create({ repo: repoPath })
|
||||
showStatus('Connected')
|
||||
Hls.DefaultConfig.loader = HlsjsIpfsLoader
|
||||
Hls.DefaultConfig.debug = false
|
||||
if (Hls.isSupported()) {
|
||||
const hls = new Hls()
|
||||
hls.config.ipfs = node
|
||||
hls.config.ipfsHash = hash
|
||||
showStatus('Video loading')
|
||||
hls.loadSource(source || 'master.m3u8')
|
||||
hls.attachMedia(video)
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||
showStatus('Video loaded', true)
|
||||
if (time) {
|
||||
video.currentTime = time
|
||||
}
|
||||
video.play()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function setUpContextMenu() {
|
||||
const video = document.getElementById('video')
|
||||
const background = document.getElementById('contextBackground')
|
||||
const menu = document.getElementById('contextMenu')
|
||||
video.oncontextmenu = e => {
|
||||
background.classList.toggle('is-hidden')
|
||||
menu.style.left = e.pageX + 'px'
|
||||
menu.style.top = e.pageY + 'px'
|
||||
e.preventDefault()
|
||||
}
|
||||
background.onClick = e => {
|
||||
e.stopPropagation()
|
||||
background.classList.toggle('is-hidden')
|
||||
}
|
||||
const url = `http://ipfsvideo.cc?hash=${
|
||||
hash
|
||||
}${
|
||||
title && '&title=' + encodeURIComponent(title)
|
||||
}${
|
||||
source && '&source=' + encodeURIComponent(source)
|
||||
}`
|
||||
document.getElementById('contextMenu-url').onClick = e => {
|
||||
e.stopPropagation()
|
||||
navigator.clipboard.writeText(url)
|
||||
background.classList.toggle('is-hidden')
|
||||
}
|
||||
document.getElementById('contextMenu-urlWithTime').onClick = e => {
|
||||
e.stopPropagation()
|
||||
navigator.clipboard.writeText(`${url}&time=${Math.round(video.currentTime)}`)
|
||||
background.classList.toggle('is-hidden')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function getUrlParameter(name) {
|
||||
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]')
|
||||
|
@ -15,44 +85,10 @@ function getUrlParameter(name) {
|
|||
|
||||
function showStatus(message, hide = false) {
|
||||
const status = document.getElementById('status')
|
||||
status.classList.toggle("is-hiding", hide)
|
||||
status.classList.toggle('is-hiding', hide)
|
||||
status.innerText = message
|
||||
}
|
||||
|
||||
function setBodyHeight() {
|
||||
document.body.style.height = window.innerHeight + "px"
|
||||
document.body.style.height = window.innerHeight + 'px'
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
setBodyHeight()
|
||||
window.addEventListener('resize', setBodyHeight)
|
||||
const hash = getUrlParameter("hash")
|
||||
const source = getUrlParameter("source") || 'master.m3u8'
|
||||
const title = getUrlParameter("title")
|
||||
if (title) {
|
||||
document.title = title
|
||||
}
|
||||
if (hash) {
|
||||
document.getElementById("help").style.display = "none"
|
||||
const video = document.getElementById('video')
|
||||
video.style.display = "block"
|
||||
const repoPath = 'ipfs-' + Math.random()
|
||||
showStatus("Connecting to IPFS")
|
||||
node = await create({ repo: repoPath })
|
||||
showStatus("Connected")
|
||||
Hls.DefaultConfig.loader = HlsjsIpfsLoader
|
||||
Hls.DefaultConfig.debug = false
|
||||
if (Hls.isSupported()) {
|
||||
const hls = new Hls()
|
||||
hls.config.ipfs = node
|
||||
hls.config.ipfsHash = hash
|
||||
showStatus("Video loading")
|
||||
hls.loadSource(source)
|
||||
hls.attachMedia(video)
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||
showStatus("Video loaded", true)
|
||||
video.play()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue