forked from remixz/umi
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add video thumbnail previews and ServiceWorker caching
- Loading branch information
Showing
12 changed files
with
194 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
const axios = require('axios') | ||
const url = require('url') | ||
const qs = require('querystring') | ||
|
||
function bifHandler (req, res) { | ||
res.setHeader('Access-Control-Allow-Origin', '*') | ||
|
||
const {query} = url.parse(req.url) | ||
const {bif} = qs.parse(query) | ||
if (!bif) return res.end() | ||
const {hostname} = url.parse(bif) | ||
if (!hostname.endsWith('crunchyroll.com')) return res.end() | ||
|
||
res.setHeader('Content-Type', 'application/octet-stream') | ||
axios.get(bif, { | ||
responseType: 'stream' | ||
}) | ||
.then(({data}) => data.pipe(res)) | ||
.catch(() => res.end()) | ||
} | ||
|
||
module.exports = bifHandler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,23 +13,25 @@ | |
</template> | ||
|
||
<script> | ||
/* global Clappr, LevelSelector */ | ||
/* global Clappr, LevelSelector, ClapprThumbnailsPlugin */ | ||
import $script from 'scriptjs' | ||
import anime from 'animejs' | ||
import api, {LOCALE, VERSION} from 'lib/api' | ||
import emoji from 'lib/emoji' | ||
import bif from 'lib/bif' | ||
import Reactotron from './Reactotron' | ||
export default { | ||
name: 'video', | ||
props: ['data', 'poster', 'id', 'seek', 'duration'], | ||
props: ['data', 'poster', 'bif', 'id', 'seek', 'duration'], | ||
components: {Reactotron}, | ||
data () { | ||
return { | ||
playerInit: false, | ||
events: [], | ||
lastEvent: null, | ||
showBlur: true | ||
showBlur: true, | ||
frames: [] | ||
} | ||
}, | ||
computed: { | ||
|
@@ -44,7 +46,7 @@ | |
} | ||
}, | ||
mounted () { | ||
$script('//cdn.jsdelivr.net/g/[email protected],[email protected]', () => { | ||
$script('//cdn.jsdelivr.net/g/[email protected],[email protected],[email protected]', () => { | ||
const self = this | ||
this.playerInit = true | ||
this.player = new Clappr.Player({ | ||
|
@@ -54,7 +56,7 @@ | |
source: this.streamUrl, | ||
poster: this.poster, | ||
disableVideoTagContextMenu: true, | ||
plugins: [LevelSelector], | ||
plugins: [LevelSelector, ClapprThumbnailsPlugin], | ||
levelSelectorConfig: { | ||
title: 'Quality', | ||
labels: { | ||
|
@@ -65,6 +67,11 @@ | |
0: '240p' | ||
} | ||
}, | ||
scrubThumbnails: { | ||
backdropHeight: null, | ||
spotlightHeight: 84, | ||
thumbs: [] | ||
}, | ||
events: { | ||
onReady () { | ||
if (self.container) { | ||
|
@@ -107,6 +114,10 @@ | |
} else if (this.room !== '') { | ||
this.wsRegisterEvents() | ||
} | ||
if (this.bif) { | ||
this.loadBif() | ||
} | ||
}) | ||
}, | ||
watch: { | ||
|
@@ -120,6 +131,7 @@ | |
if (this.room !== '') { | ||
this.playback.on(Clappr.Events.PLAYBACK_PLAY_INTENT, this.wsHandlePlay) | ||
} | ||
this.loadBif() | ||
}, | ||
room (curr) { | ||
if (curr === '') { | ||
|
@@ -223,6 +235,16 @@ | |
} | ||
}) | ||
}, | ||
async loadBif () { | ||
const thumbnailsPlugin = this.player.getPlugin('scrub-thumbnails') | ||
if (this.frames.length > 0) { | ||
thumbnailsPlugin.removeThumbnail(this.frames) | ||
} | ||
try { | ||
this.frames = await bif(this.bif) | ||
thumbnailsPlugin.addThumbnail(this.frames) | ||
} catch (err) {} | ||
}, | ||
wsJoinRoom () { | ||
const time = parseInt(this.$route.query.wsTime, 10) | ||
const playing = this.$route.query.wsPlaying | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Based on https://github.com/chemoish/videojs-bif/blob/c6fdc0c2cfc9446927062995b7e8830ae45fff0d/src/parser.js | ||
import axios from 'axios' | ||
import { fromByteArray } from 'base64-js' | ||
import { UMI_SERVER } from './api' | ||
|
||
const BIF_INDEX_OFFSET = 64 | ||
const FRAMEWISE_SEPARATION_OFFSET = 16 | ||
const NUMBER_OF_BIF_IMAGES_OFFSET = 12 | ||
const BIF_INDEX_ENTRY_LENGTH = 8 | ||
const MAGIC_NUMBER = new Uint8Array([ | ||
'0x89', | ||
'0x42', | ||
'0x49', | ||
'0x46', | ||
'0x0d', | ||
'0x0a', | ||
'0x1a', | ||
'0x0a' | ||
]) | ||
|
||
function validate (magicNumber) { | ||
let isValid = true | ||
|
||
MAGIC_NUMBER.forEach((byte, i) => { | ||
if (byte !== magicNumber[i]) { | ||
isValid = false | ||
} | ||
}) | ||
|
||
return isValid | ||
} | ||
|
||
export default function bif (url) { | ||
return new Promise(async (resolve, reject) => { | ||
const {data: buf} = await axios.get(`${UMI_SERVER}/bif?bif=${url}`, { | ||
responseType: 'arraybuffer' | ||
}) | ||
|
||
const magicNumber = new Uint8Array(buf).slice(0, 8) | ||
if (!validate(magicNumber)) { | ||
return reject(new Error('Invalid BIF file')) | ||
} | ||
|
||
const data = new DataView(buf) | ||
const framewiseSeparation = data.getUint32(FRAMEWISE_SEPARATION_OFFSET, true) || 1000 | ||
const numberOfBIFImages = data.getUint32(NUMBER_OF_BIF_IMAGES_OFFSET, true) | ||
|
||
const bifData = [] | ||
for (let i = 0, bifIndexEntryOffset = BIF_INDEX_OFFSET; i < numberOfBIFImages; i += 1, bifIndexEntryOffset += BIF_INDEX_ENTRY_LENGTH) { | ||
const bifIndexEntryTimestampOffset = bifIndexEntryOffset | ||
const bifIndexEntryAbsoluteOffset = bifIndexEntryOffset + 4 | ||
const nextBifIndexEntryAbsoluteOffset = bifIndexEntryAbsoluteOffset + BIF_INDEX_ENTRY_LENGTH | ||
|
||
const offset = data.getUint32(bifIndexEntryAbsoluteOffset, true) | ||
const nextOffset = data.getUint32(nextBifIndexEntryAbsoluteOffset, true) | ||
const length = nextOffset - offset | ||
|
||
bifData.push({ | ||
time: ((data.getUint32(bifIndexEntryTimestampOffset, true) * framewiseSeparation) / 1000) - 15, | ||
url: `data:image/jpeg;base64,${fromByteArray(new Uint8Array(buf.slice(offset, offset + length)))}` | ||
}) | ||
} | ||
|
||
resolve(bifData) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.