wip
This commit is contained in:
parent
1b0a741438
commit
43f577bfb9
31 changed files with 2004 additions and 110 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -14,3 +14,4 @@
|
|||
*.aac
|
||||
*.h263
|
||||
*.log
|
||||
http-streaming/*
|
||||
|
|
0
3gp.sh
Normal file → Executable file
0
3gp.sh
Normal file → Executable file
0
3gp2.sh
Normal file → Executable file
0
3gp2.sh
Normal file → Executable file
0
booster.sh
Normal file → Executable file
0
booster.sh
Normal file → Executable file
|
@ -1,54 +1,70 @@
|
|||
#EXTM3U
|
||||
#EXT-X-VERSION:7
|
||||
#EXT-X-VERSION:4
|
||||
#EXT-X-TARGETDURATION:10
|
||||
#EXT-X-MEDIA-SEQUENCE:0
|
||||
#EXT-X-ALLOW-CACHE:YES
|
||||
#EXT-X-TARGETDURATION:11
|
||||
#EXTINF:10.005397,
|
||||
#EXT-X-BYTERANGE:160151@0
|
||||
#EXT-X-PLAYLIST-TYPE:VOD
|
||||
#EXTINF:10.005900,
|
||||
#EXT-X-BYTERANGE:175404@0
|
||||
#EXT-X-BYTERANGE:2624741@0
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@160151
|
||||
#EXTINF:10.004900,
|
||||
#EXT-X-BYTERANGE:174840@175404
|
||||
#EXT-X-BYTERANGE:2624741@2624741
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160152@320302
|
||||
#EXTINF:10.004900,
|
||||
#EXT-X-BYTERANGE:174840@350244
|
||||
#EXT-X-BYTERANGE:2624741@5249482
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@480454
|
||||
#EXTINF:10.004578,
|
||||
#EXT-X-BYTERANGE:174840@525084
|
||||
#EXT-X-BYTERANGE:2624741@7874223
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@640605
|
||||
#EXTINF:10.005056,
|
||||
#EXT-X-BYTERANGE:174840@699924
|
||||
#EXT-X-BYTERANGE:2624741@10498964
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:9.978776,
|
||||
#EXT-X-BYTERANGE:159734@800756
|
||||
#EXTINF:9.978611,
|
||||
#EXT-X-BYTERANGE:174464@874764
|
||||
#EXT-X-BYTERANGE:2624741@13123705
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@960490
|
||||
#EXTINF:10.005222,
|
||||
#EXT-X-BYTERANGE:174840@1049228
|
||||
#EXT-X-BYTERANGE:2624741@15748446
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160152@1120641
|
||||
#EXTINF:10.004900,
|
||||
#EXT-X-BYTERANGE:174840@1224068
|
||||
#EXT-X-BYTERANGE:2624741@18373187
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@1280793
|
||||
#EXTINF:10.004889,
|
||||
#EXT-X-BYTERANGE:174840@1398908
|
||||
#EXT-X-BYTERANGE:2624741@20997928
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@1440944
|
||||
#EXTINF:10.004744,
|
||||
#EXT-X-BYTERANGE:174840@1573748
|
||||
#EXT-X-BYTERANGE:2624741@23622669
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:9.978776,
|
||||
#EXT-X-BYTERANGE:159734@1601095
|
||||
#EXTINF:9.978778,
|
||||
#EXT-X-BYTERANGE:174464@1748588
|
||||
#EXT-X-BYTERANGE:2624741@26247410
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@1760829
|
||||
#EXTINF:10.005056,
|
||||
#EXT-X-BYTERANGE:174840@1923052
|
||||
#EXT-X-BYTERANGE:2624741@28872151
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@1920980
|
||||
#EXTINF:10.004733,
|
||||
#EXT-X-BYTERANGE:174840@2097892
|
||||
#EXT-X-BYTERANGE:2624741@31496892
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160152@2081131
|
||||
#EXTINF:10.005056,
|
||||
#EXT-X-BYTERANGE:174840@2272732
|
||||
#EXT-X-BYTERANGE:2624741@34121633
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:160151@2241283
|
||||
#EXTINF:10.004900,
|
||||
#EXT-X-BYTERANGE:174840@2447572
|
||||
#EXT-X-BYTERANGE:2624741@36746374
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXTINF:0.119819,
|
||||
#EXT-X-BYTERANGE:2163@2401434
|
||||
#EXTINF:0.119822,
|
||||
#EXT-X-BYTERANGE:2256@2622412
|
||||
#EXT-X-BYTERANGE:2624741@39371115
|
||||
caminandes-llamigos.webm.audio.mp3
|
||||
#EXT-X-ENDLIST
|
|
@ -3,53 +3,37 @@
|
|||
#EXT-X-TARGETDURATION:10
|
||||
#EXT-X-MEDIA-SEQUENCE:0
|
||||
#EXT-X-PLAYLIST-TYPE:VOD
|
||||
#EXT-X-MAP:URI="caminandes-llamigos.webm.audio.mp3.mp4.mp4",BYTERANGE="755@0"
|
||||
#EXT-X-MAP:URI="init.mp4"
|
||||
#EXTINF:10.005896,
|
||||
#EXT-X-BYTERANGE:163302@755
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0000.mp4
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:163302@164057
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0001.mp4
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:163303@327359
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0002.mp4
|
||||
#EXTINF:10.004580,
|
||||
#EXT-X-BYTERANGE:163302@490662
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0003.mp4
|
||||
#EXTINF:10.005057,
|
||||
#EXT-X-BYTERANGE:163302@653964
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0004.mp4
|
||||
#EXTINF:9.978617,
|
||||
#EXT-X-BYTERANGE:162877@817266
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0005.mp4
|
||||
#EXTINF:10.005215,
|
||||
#EXT-X-BYTERANGE:163302@980143
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0006.mp4
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:163303@1143445
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0007.mp4
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:163302@1306748
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0008.mp4
|
||||
#EXTINF:10.004739,
|
||||
#EXT-X-BYTERANGE:163302@1470050
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0009.mp4
|
||||
#EXTINF:9.978776,
|
||||
#EXT-X-BYTERANGE:162877@1633352
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0010.mp4
|
||||
#EXTINF:10.005057,
|
||||
#EXT-X-BYTERANGE:163302@1796229
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0011.mp4
|
||||
#EXTINF:10.004739,
|
||||
#EXT-X-BYTERANGE:163302@1959531
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0012.mp4
|
||||
#EXTINF:10.005057,
|
||||
#EXT-X-BYTERANGE:163303@2122833
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0013.mp4
|
||||
#EXTINF:10.004898,
|
||||
#EXT-X-BYTERANGE:163302@2286136
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0014.mp4
|
||||
#EXTINF:0.119819,
|
||||
#EXT-X-BYTERANGE:2270@2449438
|
||||
caminandes-llamigos.webm.audio.mp3.mp4.mp4
|
||||
caminandes-llamigos.webm.audio.mp3.0015.mp4
|
||||
#EXT-X-ENDLIST
|
||||
|
|
157
index.html
157
index.html
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>HLS WebM test</title>
|
||||
<link rel=stylesheet type=text/css href=video-js/video-js.css>
|
||||
</head>
|
||||
<body>
|
||||
<h1>HLS WebM test</h1>
|
||||
|
@ -15,36 +16,88 @@
|
|||
|
||||
<h2>Caminandes - Llamigos</h2>
|
||||
|
||||
<p>HLS with AAC audio and VP9-in-MP4 at several resolutions:</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<h3>VP9</h3>
|
||||
|
||||
<!--
|
||||
<p>HLS with AAC-in-MP4 audio and VP9-in-MP4 at several resolutions:</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-aac.m3u8>
|
||||
</video>
|
||||
|
||||
<p>HLS with MP3 audio and VP9-in-MP4 at several resolutions:</p>
|
||||
<video id=hls1b controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3.m3u8?>
|
||||
<p>HLS with Opus-in-MP4 audio and VP9-in-MP4 at several resolutions:</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-opus.m3u8>
|
||||
</video>
|
||||
-->
|
||||
|
||||
<h3>Mixed codecs</h3>
|
||||
|
||||
<p>HLS with ((VP9-fMP4 + (Opus-fMP4 | MP3)) | (MJPEG-QuickTime + MP3)):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-opus-mp3-mjpeg.m3u8>
|
||||
</video>
|
||||
|
||||
<p>HLS with no audio and VP9-in-MP4 at several resolutions:</p>
|
||||
<video id=hls1c controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9.m3u8>
|
||||
<h3>VP9 only</h3>
|
||||
|
||||
<p>HLS with (VP9-fMP4 + (Opus-fMP4 | MP3)):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3-opus.m3u8>
|
||||
</video>
|
||||
|
||||
<h2>Short polyphon test</h2>
|
||||
<h3>MJPEG only</h3>
|
||||
|
||||
<p>HLS with AAC audio and VP9, VP8, and H.264 video:</p>
|
||||
<video id=hls2 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=av-aac-mp4.m3u8>
|
||||
<p>HLS standalone (MJPEG-MP3-MP4):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=standalone-mjpeg-mp3.m3u8>
|
||||
</video>
|
||||
<p>HLS standalone (MJPEG-AAC-MP4):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=standalone-mjpeg-aac.m3u8>
|
||||
</video>
|
||||
<p>HLS standalone (MJPEG-noaudio-MP4):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=standalone-mjpeg.m3u8>
|
||||
</video>
|
||||
|
||||
<p>Same, with a flat WebM fallback source:</p>
|
||||
<video id=hls3 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=av-aac-mp4.m3u8>
|
||||
<source type="video/webm" src=polyphon-vp8-vorbis.webm>
|
||||
<p>HLS standalone (MJPEG-noaudio-QuickTime):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=standalone-mjpeg-mp3-mov.m3u8>
|
||||
</video>
|
||||
<p>HLS standalone (MJPEG-noaudio-QuickTime):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=standalone-mjpeg-aac-mov.m3u8>
|
||||
</video>
|
||||
<p>HLS standalone (MJPEG-noaudio-QuickTime):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=standalone-mjpeg-mov.m3u8>
|
||||
</video>
|
||||
|
||||
<p>Flat QT with (MJPEG-MP3-QuickTime):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/quicktime" src=standalone-mjpeg-mp3.mov>
|
||||
</video>
|
||||
<p>Flat QT with (MJPEG-AAC-QuickTime):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/quicktime" src=standalone-mjpeg-aac.mov>
|
||||
</video>
|
||||
<p>Flat QT with (MJPEG-noaudio-QuickTime):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/quicktime" src=standalone-mjpeg.mov>
|
||||
</video>
|
||||
|
||||
<!--
|
||||
<script src=video-js/alt/video.core.js></script>
|
||||
<script src=videojs-http-streaming.js></script>
|
||||
-->
|
||||
<script src="node_modules/video.js/dist/video.js"></script>
|
||||
<!--
|
||||
<script src="node_modules/video.js/dist/alt/video.core.js"></script>
|
||||
<script src="http-streaming/dist/videojs-http-streaming.js"></script>
|
||||
-->
|
||||
|
||||
<script>
|
||||
if (hls1.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
let video = document.createElement('video');
|
||||
if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
hls.textContent = 'native HLS playback supported';
|
||||
hls.style.color = 'green';
|
||||
} else {
|
||||
|
@ -52,26 +105,63 @@
|
|||
hls.style.color = 'red';
|
||||
}
|
||||
if (typeof MediaSource == 'function') {
|
||||
if (MediaSource.isTypeSupported('video/mp4; codecs="vp09.00.10.08"') &&
|
||||
MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.02"')) {
|
||||
mse.textContent = 'MSE supports VP9 & AAC-LC in MP4';
|
||||
let video = [];
|
||||
let audio = [];
|
||||
if (MediaSource.isTypeSupported('video/webm; codecs="vp8"')) {
|
||||
video.push('VP8-in-WebM (vp8)');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('video/webm; codecs="vp9"')) {
|
||||
video.push('VP9-in-WebM (vp9)');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('video/mp4; codecs="vp09.00.10.08"')) {
|
||||
video.push('VP9-in-MP4 (vp09)');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('video/mp4; codecs="vp9"')) {
|
||||
video.push('VP9-in-MP4 (vp9)');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.02"')) {
|
||||
audio.push('AAC-in-MP4');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.34"')) {
|
||||
audio.push('MP3-in-MP4 (mp4a.40.34)');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.6b"')) {
|
||||
audio.push('MP3-in-MP4 (mp4a.6b)');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('audio/mp4; codecs="mp3"')) {
|
||||
audio.push('MP3-in-MP4 (mp3)');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('audio/mp4; codecs="opus"')) {
|
||||
audio.push('Opus-in-MP4');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('audio/webm; codecs="opus"')) {
|
||||
audio.push('Opus-in-WebM');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('audio/webm; codecs="vorbis"')) {
|
||||
audio.push('Vorbis-in-WebM');
|
||||
}
|
||||
if (MediaSource.isTypeSupported('audio/mp3')) {
|
||||
audio.push('MP3 raw');
|
||||
}
|
||||
|
||||
if (video.length > 0 && audio.length > 0) {
|
||||
mse.style.color = 'green';
|
||||
} else {
|
||||
mse.textContent = 'MSE doesn\'t support one of VP9 or AAC in MP4';
|
||||
mse.style.color = 'orange';
|
||||
}
|
||||
mse.textContent = `MSE supports video: ${video.join(', ')}; audio: ${audio.join(',')}`;
|
||||
} else {
|
||||
mse.textContent = 'MSE not supported';
|
||||
mse.style.color = 'red';
|
||||
}
|
||||
if (hls2.canPlayType('video/webm')) {
|
||||
if (video.canPlayType('video/webm')) {
|
||||
webm.textContent = 'flat WebM generic supported';
|
||||
webm.style.color = 'green';
|
||||
} else {
|
||||
webm.textContent = 'flat WebM generic not supported';
|
||||
webm.style.color = 'red';
|
||||
}
|
||||
if (hls2.canPlayType('video/webm; codecs="vp8, vorbis"')) {
|
||||
if (video.canPlayType('video/webm; codecs="vp8, vorbis"')) {
|
||||
webm2.textContent = 'flat WebM VP8/Vorbis supported';
|
||||
webm2.style.color = 'green';
|
||||
} else {
|
||||
|
@ -85,6 +175,27 @@
|
|||
wasm.textContent = 'no WebAssembly support';
|
||||
wasm.style.color = 'red';
|
||||
}
|
||||
|
||||
var playerConfig = {
|
||||
responsive: true,
|
||||
controlBar: {
|
||||
volumePanel: {
|
||||
vertical: true,
|
||||
inline: false
|
||||
}
|
||||
},
|
||||
techOrder: [ 'html5' ],
|
||||
html5: {}
|
||||
};
|
||||
videojs.log.level('debug');
|
||||
|
||||
if (window.MediaSource && MediaSource.isTypeSupported('video/mp4; codecs="vp09,opus"')) {
|
||||
for (let video of document.querySelectorAll('video')) {
|
||||
video.classList.add('video-js');
|
||||
video.classList.add('vjs-default-skin');
|
||||
videojs(video, playerConfig);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
0
make-flat.sh
Normal file → Executable file
0
make-flat.sh
Normal file → Executable file
40
make-hls-new.sh
Executable file
40
make-hls-new.sh
Executable file
|
@ -0,0 +1,40 @@
|
|||
MOVFLAGS="-movflags +frag_keyframe+empty_moov+default_base_moof+faststart"
|
||||
HLSFLAGS="-hls_time 10 -hls_list_size 0 -hls_segment_type fmp4 -hls_flags single_file -hls_playlist_type vod"
|
||||
BITRATE_HI="-b:v 3840k"
|
||||
BITRATE_LO="-b:v 2560k"
|
||||
|
||||
VIDEO_H264="-vcodec h264 $BITRATE_HI"
|
||||
VIDEO_JPEG="-vcodec mjpeg $BITRATE_HI"
|
||||
VIDEO_VP8="-vcodec libvpx -cpu-used 4 $BITRATE_HI"
|
||||
VIDEO_VP9="-vcodec libvpx-vp9 -row-mt 1 -cpu-used 4 $BITRATE_LO"
|
||||
|
||||
AUDIO_VORBIS="-acodec libvorbis -ac 2 -ar 44100 -vb 128k"
|
||||
AUDIO_OPUS="-acodec libopus -ac 2 -ar 48000 -vb 96k"
|
||||
AUDIO_AAC="-ac 2 -ar 44100 -vb 128k"
|
||||
AUDIO_MP3="-acodec libmp3lame -ac 2 -ar 44100 -vb 128k"
|
||||
|
||||
INFILE=polyphon.ogv
|
||||
|
||||
# Flat WebM
|
||||
ffmpeg -i $INFILE $VIDEO_VP8 $AUDIO_VORBIS -y new-vp8.webm || exit 1
|
||||
ffmpeg -i $INFILE $VIDEO_VP9 $AUDIO_OPUS -y new-vp9.webm || exit 1
|
||||
|
||||
# Flat Quicktime
|
||||
ffmpeg -i $INFILE -s 1280x720 -vcodec mpeg2video $BITRATE_HI $AUDIO_MP3 $MOVFLAGS -y new-mpeg2.mov || exit 1
|
||||
ffmpeg -i $INFILE -s 640x360 -vcodec mpeg1video $BITRATE_HI $AUDIO_MP3 $MOVFLAGS -y new-mpeg1.mov || exit 1
|
||||
ffmpeg -i $INFILE -s 320x180 -vcodec cinepak $BITRATE_HI $AUDIO_MP3 $MOVFLAGS -y new-cinepak.mov || exit 1
|
||||
#ffmpeg -i $INFILE -s 320x180 -vcodec rpza $BITRATE_HI $AUDIO_MP3 $MOVFLAGS -y new-rpza.mov || exit 1
|
||||
ffmpeg -i $INFILE -s 320x180 $VIDEO_JPEG $AUDIO_MP3 $MOVFLAGS -y new-mjpeg.mov || exit 1
|
||||
|
||||
|
||||
exit 0
|
||||
|
||||
# Audio for HLS
|
||||
ffmpeg -i $INFILE -vn $AUDIO_AAC $HLSFLAGS -hls_segment_filename new-aac.mp4 -y new-aac.m3u8 || exit 1
|
||||
ffmpeg -i $INFILE -vn $AUDIO_OPUS $HLSFLAGS -hls_segment_filename new-opus.mp4 -y new-opus.m3u8 || exit 1
|
||||
|
||||
# Video for HLS
|
||||
ffmpeg -i $INFILE -an $VIDEO_VP9 $HLSFLAGS -hls_segment_filename new-vp9.mp4 -y new-vp9.m3u8 || exit 1
|
||||
ffmpeg -i $INFILE -an $VIDEO_JPEG $HLSFLAGS -hls_segment_filename new-jpeg.mp4 -y new-jpeg.m3u8 || exit 1
|
||||
ffmpeg -i $INFILE -an -vcodec mpeg2video $BITRATE_HI $HLSFLAGS -hls_segment_filename new-mpeg2.mp4 -y new-mpeg2.m3u8 || exit 1
|
||||
ffmpeg -i $INFILE -an -vcodec mpeg1video $BITRATE_HI $HLSFLAGS -hls_segment_filename new-mpeg1.mp4 -y new-mpeg1.m3u8 || exit 1
|
0
make-hls.sh
Normal file → Executable file
0
make-hls.sh
Normal file → Executable file
2
make-hls2.sh
Normal file → Executable file
2
make-hls2.sh
Normal file → Executable file
|
@ -15,7 +15,6 @@ AUDIO_MP3="-acodec libmp3lame -ac 2 -ar 44100 -vb 128k"
|
|||
AUDIO_MP2="-acodec mp2 -ac 2 -ar 44100 -vb 128k"
|
||||
AUDIO_ALAC="-acodec alac -sample_fmt s16 -ac 1 -ar 22050"
|
||||
|
||||
|
||||
if false
|
||||
then
|
||||
ffmpeg -i polyphon.ogv -vn $AUDIO_MP3 -y polyphon-mp3.mp3
|
||||
|
@ -23,6 +22,7 @@ ffmpeg -i polyphon.ogv -vn $AUDIO_MP3 $MOVFLAGS -y polyphon-mp3.mp4
|
|||
ffmpeg -i polyphon.ogv -vn $AUDIO_AAC $MOVFLAGS -y polyphon-aac.mp4
|
||||
ffmpeg -i polyphon.ogv -vn $AUDIO_OPUS -y polyphon-opus.webm
|
||||
ffmpeg -i polyphon.ogv -vn $AUDIO_OPUS $MOVFLAGS -y polyphon-opus.mp4
|
||||
ffmpeg -i polyphon.ogv -vn $AUDIO_OPUS $MOVFLAGS -tag:a Opus -y polyphon-opus-tagged.mp4
|
||||
ffmpeg -i polyphon.ogv -vn $AUDIO_VORBIS $MOVFLAGS -y polyphon-vorbis.mp4
|
||||
ffmpeg -i polyphon.ogv -vn $AUDIO_MP2 $MOVFLAGS -y polyphon-mp2.mp4
|
||||
ffmpeg -i polyphon.ogv -vn $AUDIO_ALAC $MOVFLAGS -y polyphon-alac.mp4
|
||||
|
|
40
make-standalone.sh
Executable file
40
make-standalone.sh
Executable file
|
@ -0,0 +1,40 @@
|
|||
MOVFLAGS="-movflags +frag_keyframe+empty_moov+default_base_moof+faststart"
|
||||
HLSFLAGS="-hls_time 10 -hls_list_size 0 -hls_segment_type fmp4 -hls_flags single_file -hls_playlist_type vod"
|
||||
RES_MAIN="-s 854x480"
|
||||
RES_SMALL="-s 256x144"
|
||||
BITRATE_HI="-b:v 1024k"
|
||||
BITRATE_LO="-b:v 768k"
|
||||
|
||||
VIDEO_H264="-vcodec h264 $BITRATE_HI"
|
||||
VIDEO_JPEG="-vcodec mjpeg $BITRATE_LO -s 426x240"
|
||||
VIDEO_VP8="-vcodec libvpx -cpu-used 4 $BITRATE_HI"
|
||||
VIDEO_VP9="-vcodec libvpx-vp9 -row-mt 1 -cpu-used 4 $BITRATE_LO"
|
||||
|
||||
AUDIO_VORBIS="-acodec libvorbis -ac 2 -ar 44100 -vb 128k"
|
||||
AUDIO_OPUS="-acodec libopus -ac 2 -ar 48000 -vb 96k"
|
||||
AUDIO_MP3="-acodec libmp3lame -ac 2 -ar 44100 -vb 128k"
|
||||
AUDIO_AAC="-ac 2 -ar 44100 -vb 128k"
|
||||
|
||||
#INFILE=polyphon.ogv
|
||||
INFILE=caminandes-llamigos.webm
|
||||
|
||||
# Flat WebM
|
||||
ffmpeg -i $INFILE $RES_MAIN $VIDEO_VP9 $AUDIO_OPUS -y standalone-vp9-opus.webm || exit 1
|
||||
ffmpeg -i $INFILE $RES_MAIN $VIDEO_VP9 -an -y standalone-vp9.webm || exit 1
|
||||
|
||||
ffmpeg -i $INFILE $RES_MAIN $VIDEO_VP8 $AUDIO_VORBIS -y standalone-vp8-vorbis.webm || exit 1
|
||||
ffmpeg -i $INFILE $RES_MAIN $VIDEO_VP8 -an -y standalone-vp8.webm || exit 1
|
||||
|
||||
# Flat MJPEG+MP3/AAC/none mov
|
||||
ffmpeg -i $INFILE $RES_SMALL $VIDEO_JPEG -an $MOVFLAGS -y standalone-mjpeg.mov || exit 1
|
||||
ffmpeg -i $INFILE $RES_SMALL $VIDEO_JPEG $AUDIO_MP3 $MOVFLAGS -y standalone-mjpeg-mp3.mov || exit 1
|
||||
ffmpeg -i $INFILE $RES_SMALL $VIDEO_JPEG $AUDIO_AAC $MOVFLAGS -y standalone-mjpeg-aac.mov || exit 1
|
||||
|
||||
# Standalone HLS
|
||||
ffmpeg -i $INFILE $RES_SMALL $VIDEO_JPEG $AUDIO_AAC $HLSFLAGS -hls_segment_filename standalone-mjpeg-aac.mp4 -y standalone-mjpeg-aac.m3u8 || exit 1
|
||||
ffmpeg -i $INFILE $RES_SMALL $VIDEO_JPEG $AUDIO_MP3 $HLSFLAGS -hls_segment_filename standalone-mjpeg-mp3.mp4 -y standalone-mjpeg-mp3.m3u8 || exit 1
|
||||
ffmpeg -i $INFILE $RES_SMALL $VIDEO_JPEG -an $HLSFLAGS -hls_segment_filename standalone-mjpeg.mp4 -y standalone-mjpeg.m3u8 || exit 1
|
||||
|
||||
ffmpeg -i $INFILE $RES_MAIN $VIDEO_VP9 $AUDIO_AAC $HLSFLAGS -hls_segment_filename standalone-vp9-aac.mp4 -y standalone-vp9-aac.m3u8 || exit 1
|
||||
ffmpeg -i $INFILE $RES_MAIN $VIDEO_VP9 $AUDIO_MP3 $HLSFLAGS -hls_segment_filename standalone-vp9-mp3.mp4 -y standalone-vp9-mp3.m3u8 || exit 1
|
||||
ffmpeg -i $INFILE $RES_MAIN $VIDEO_VP9 -an $HLSFLAGS -hls_segment_filename standalone-vp9.mp4 -y standalone-vp9.m3u8 || exit 1
|
0
mov.sh
Normal file → Executable file
0
mov.sh
Normal file → Executable file
0
mp4.sh
Normal file → Executable file
0
mp4.sh
Normal file → Executable file
0
mpeg.sh
Normal file → Executable file
0
mpeg.sh
Normal file → Executable file
207
new.html
Normal file
207
new.html
Normal file
|
@ -0,0 +1,207 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>HLS VP9/fMP4 test</title>
|
||||
<link rel=stylesheet type=text/css href=video-js/video-js.css>
|
||||
</head>
|
||||
<body>
|
||||
<h1>HLS WebM test</h1>
|
||||
|
||||
<p id=hls>Checking HLS support...</p>
|
||||
<p id=mse>Checking MSE VP9 support...</p>
|
||||
<p id=webm>Checking flat WebM VP8 / Vorbis support...</p>
|
||||
<p id=wasm>Checking WebAssembly support...</p>
|
||||
|
||||
<h2>Caminandes - Llamigos</h2>
|
||||
|
||||
<p>HLS with VP9-in-MP4 video with Opus-in-MP4 or AAC audio.</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=new.m3u8>
|
||||
<source type="video/webm; codecs="vp8, vorbis"" src=caminandes-llamigos.webm.flat.webm>
|
||||
<source type="video/quicktime; codecs="jpeg, mp3"" src=polyphon-jpeg-mp3.mov>
|
||||
</video>
|
||||
|
||||
<p>Flat WebM VP8/Vorbis</p>
|
||||
<video id=webm controls width=640 height=360>
|
||||
<source type="video/webm; codecs="vp8, vorbis"" src=new-vp8.webm>
|
||||
</video>
|
||||
|
||||
<p>Flat Quicktime MJPEG/MP3</p>
|
||||
<video id=mjpeg controls width=640 height=360>
|
||||
<source type="video/quicktime" src=new-mjpeg.mov>
|
||||
</video>
|
||||
|
||||
<p>Flat Quicktime MPEG-2</p>
|
||||
<video id=mjpeg controls width=640 height=360>
|
||||
<source type="video/quicktime" src=new-mpeg2.mov>
|
||||
</video>
|
||||
|
||||
<p>Flat Quicktime MPEG-1</p>
|
||||
<video id=mjpeg controls width=640 height=360>
|
||||
<source type="video/quicktime" src=new-mpeg1.mov>
|
||||
</video>
|
||||
|
||||
<p>Flat Quicktime Cinepak</p>
|
||||
<video id=mjpeg controls width=640 height=360>
|
||||
<source type="video/quicktime" src=new-cinepak.mov>
|
||||
</video>
|
||||
|
||||
<p>HLS MJPEG MP4 alone (no audio)</p>
|
||||
<video id=mjpeg-hls controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=new-jpeg.m3u8>
|
||||
</video>
|
||||
|
||||
<p>Flat MJPEG MP4 alone (no audio)</p>
|
||||
<video id=mjpeg-hls controls width=640 height=360>
|
||||
<source type=video/mp4 src=new-jpeg.mp4>
|
||||
</video>
|
||||
|
||||
<p>HLS MPEG-1 MP4 alone (no audio)</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=new-mpeg1.m3u8>
|
||||
</video>
|
||||
|
||||
<p>Flat MPEG-1 MP4 alone (no audio)</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=video/mp4 src=new-mpeg1.mp4>
|
||||
</video>
|
||||
|
||||
<p>HLS MPEG-2 MP4 alone (no audio)</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=new-mpeg2.m3u8>
|
||||
</video>
|
||||
|
||||
<p>Flat MPEG-2 MP4 alone (no audio)</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=video/mp4 src=new-mpeg2.mp4>
|
||||
</video>
|
||||
|
||||
<script>
|
||||
if (hls1.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
hls.textContent = 'native HLS playback supported';
|
||||
hls.style.color = 'green';
|
||||
} else {
|
||||
hls.textContent = 'no native HLS';
|
||||
hls.style.color = 'red';
|
||||
}
|
||||
if (typeof MediaSource == 'function') {
|
||||
let codecs = [
|
||||
['VP9-in-WebM', 'video/webm; codecs="vp9"'],
|
||||
['Opus-in-WebM', 'audio/webm; codecs="opus"'],
|
||||
['VP9-in-MP4', 'video/mp4; codecs="vp09.00.10.08"'],
|
||||
['Opus-in-MP4', 'audio/mp4; codecs="opus"'],
|
||||
];
|
||||
let yes = [];
|
||||
let no = [];
|
||||
for (let [name, mime] of codecs) {
|
||||
if (MediaSource.isTypeSupported(mime)) {
|
||||
yes.push(name);
|
||||
} else {
|
||||
no.push(name);
|
||||
}
|
||||
}
|
||||
if (yes.length == codecs.length) {
|
||||
mse.textContent = 'MSE supports ' + yes.join(', ');
|
||||
mse.style.color = 'green';
|
||||
} else {
|
||||
mse.textContent = 'MSE supports ' + yes.join(', ') + ' but not ' + no.join(', ');
|
||||
mse.style.color = 'orange';
|
||||
}
|
||||
} else {
|
||||
mse.textContent = 'MSE not supported';
|
||||
mse.style.color = 'red';
|
||||
}
|
||||
if (hls1.canPlayType('video/webm; codecs="vp8, vorbis"')) {
|
||||
webm.textContent = 'flat WebM VP8/Vorbis supported';
|
||||
webm.style.color = 'green';
|
||||
} else {
|
||||
webm.textContent = 'flat WebM VP8/Vorbis not supported';
|
||||
webm.style.color = 'red';
|
||||
}
|
||||
if (typeof WebAssembly == 'object') {
|
||||
wasm.textContent = 'WebAssembly supported';
|
||||
wasm.style.color = 'green';
|
||||
} else {
|
||||
wasm.textContent = 'no WebAssembly support';
|
||||
wasm.style.color = 'red';
|
||||
}
|
||||
</script>
|
||||
<!--
|
||||
<script src="node_modules/video.js/dist/alt/video.core.js"></script>
|
||||
<script src="http-streaming/dist/videojs-http-streaming.js"></script>
|
||||
|
||||
<script src=videojs-ogvjs.js></script>
|
||||
-->
|
||||
<script type="text/disabled">
|
||||
var playerConfig = {
|
||||
responsive: true,
|
||||
controlBar: {
|
||||
volumePanel: {
|
||||
vertical: true,
|
||||
inline: false
|
||||
}
|
||||
},
|
||||
techOrder: [ 'html5' ],
|
||||
html5: {}
|
||||
};
|
||||
|
||||
function can(mime) {
|
||||
return (typeof MediaSource == 'function') && MediaSource.isTypeSupported(mime);
|
||||
}
|
||||
var vp9 = can('video/mp4; codecs="vp09.00.10.08"');
|
||||
var opus = can('audio/mp4; codecs="opus"');
|
||||
var aac = can('audio/mp4; codecs="mp4a.40.02"');
|
||||
console.log({
|
||||
vp9, opus, aac
|
||||
})
|
||||
var mse = vp9 && (opus || aac);
|
||||
if (mse) {
|
||||
// enable streaming plugin
|
||||
playerConfig.html5 = {
|
||||
vhs: {
|
||||
overrideNative: true,
|
||||
useDevicePixelRatio: true
|
||||
},
|
||||
nativeAudioTracks: false,
|
||||
nativeVideoTracks: false
|
||||
};
|
||||
console.log('will do mse');
|
||||
|
||||
var m3u8 = null;
|
||||
for (let source of hls1.querySelectorAll('source')) {
|
||||
if (source.type == 'application/vnd.apple.mpegurl') {
|
||||
m3u8 = source;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
videojs.log.level('debug');
|
||||
|
||||
hls1.classList.add('video-js');
|
||||
hls1.classList.add('vjs-default-skin');
|
||||
var vjs1 = videojs(hls1, playerConfig);
|
||||
|
||||
vjs1.on('error', function failover() {
|
||||
console.log('got error');
|
||||
var error = vjs1.error();
|
||||
if (error && error.code == MediaError.MEDIA_ERR_DECODE) {
|
||||
console.log('saw its a decode error');
|
||||
// HLS reports this if it can't find a codec it likes
|
||||
console.log(m3u8);
|
||||
if (mse && m3u8) {
|
||||
console.log('going to m3u8: ' + m3u8.getAttribute('src'));
|
||||
vjs1.src([{
|
||||
src: m3u8.getAttribute('src'),
|
||||
type: m3u8.getAttribute('type')
|
||||
}]);
|
||||
vjs1.reset();
|
||||
m3u8 = null;
|
||||
}
|
||||
}
|
||||
vjs1.off('error', failover);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
234
ogv-aac.html
Normal file
234
ogv-aac.html
Normal file
|
@ -0,0 +1,234 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>HLS WebM test</title>
|
||||
<link rel=stylesheet type=text/css href=video-js/video-js.css>
|
||||
</head>
|
||||
<body>
|
||||
<h1>HLS WebM test</h1>
|
||||
|
||||
<p id=hls>Checking HLS support...</p>
|
||||
<p id=mse>Checking MSE VP9 support...</p>
|
||||
<p id=webm>Checking flat WebM VP8 / Vorbis support...</p>
|
||||
<p id=wasm>Checking WebAssembly support...</p>
|
||||
|
||||
<h2>Caminandes - Llamigos</h2>
|
||||
|
||||
<p>HLS with VP9-in-MP4 video and Opus-in-MP4, AAC-in-MP4, and MP3 audio. Flat WebM fallback with ogv.js loader.</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-opus-aac-mp3.m3u8>
|
||||
<!--<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3-opus.m3u8>-->
|
||||
<!--<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3ts-opus.m3u8>-->
|
||||
<!--<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3-vorbis.m3u8>-->
|
||||
<source type="video/webm; codecs="vp8, vorbis"" src=caminandes-llamigos.webm.flat.webm>
|
||||
<source type="video/quicktime; codecs="jpeg, mp3"" src=polyphon-jpeg-mp3.mov>
|
||||
</video>
|
||||
|
||||
<p>Desired behavior:</p>
|
||||
<ul>
|
||||
<li>Firefox/Chrome: play via MSE with VP9/Opus (working)</li>
|
||||
<li>Desktop Safari with VP9 support: play via MSE with VP9/AAC or MP3 (currently MP3 fails)</li>
|
||||
<li>iOS Safari with VP9 support: play native HLS with VP9/AAC or MP3 (works)</li>
|
||||
<li>Older iOS and desktop Safari without VP9: play via ogv.js with WebM VP8/Vorbis (WebKit issue with some devices, in progress)</li>
|
||||
<li>Older iOS and desktop Safari without WebAssembly or with JS off: play backup MJPEG :D (HLS will take over but fail without JS)</li>
|
||||
<li>Very old Firefox/Chrome: play native WebM VP8/Vorbis</li>
|
||||
</ul>
|
||||
|
||||
<!--
|
||||
<p>HLS with VP9 video and Opus, AAC, and MP3 audio. Flag WebM fallback.</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-opus-aac-mp3.m3u8>
|
||||
<source type=video/webm src=caminandes-llamigos.webm.flat.webm>
|
||||
</video>
|
||||
|
||||
<p>Expected behavior:</p>
|
||||
<ul>
|
||||
<li>Firefox/Chrome: MSE VP9/Opus (AAC for now)</li>
|
||||
<li>Desktop Safari with VP9 support: MSE VP9/MP3 (AAC for now?)</li>
|
||||
<li>iOS Safari with VP9 support: HLS VP9/MP3 (AAC for now?)</li>
|
||||
<li>Older iOS and desktop Safari without VP9: ogv.js VP8/Vorbis</li>
|
||||
<li>Very old Firefox/Chrome: native WebM VP8/Vorbis</li>
|
||||
</ul>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<p>HLS with VP9 video and AAC audio. Flag WebM fallback.</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-aac.m3u8>
|
||||
<source type=video/webm src=caminandes-llamigos.webm.flat.webm>
|
||||
</video>
|
||||
|
||||
<p>Expected behavior:</p>
|
||||
<ul>
|
||||
<li>Firefox/Chrome: MSE VP9/Opus (AAC for now)</li>
|
||||
<li>Desktop Safari with VP9 support: MSE VP9/MP3 (AAC for now?)</li>
|
||||
<li>iOS Safari with VP9 support: HLS VP9/MP3 (AAC for now?)</li>
|
||||
<li>Older iOS and desktop Safari without VP9: ogv.js VP8/Vorbis</li>
|
||||
<li>Very old Firefox/Chrome: native WebM VP8/Vorbis</li>
|
||||
</ul>
|
||||
-->
|
||||
|
||||
<script>
|
||||
if (hls1.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
hls.textContent = 'native HLS playback supported';
|
||||
hls.style.color = 'green';
|
||||
} else {
|
||||
hls.textContent = 'no native HLS';
|
||||
hls.style.color = 'red';
|
||||
}
|
||||
if (typeof MediaSource == 'function') {
|
||||
let codecs = [
|
||||
['VP9-in-MP4', 'video/mp4; codecs="vp09.00.10.08"'],
|
||||
['Opus-in-WebM', 'audio/webm; codecs="opus"'],
|
||||
['MP3', 'audio/mp3'],
|
||||
];
|
||||
let yes = [];
|
||||
let no = [];
|
||||
for (let [name, mime] of codecs) {
|
||||
if (MediaSource.isTypeSupported(mime)) {
|
||||
yes.push(name);
|
||||
} else {
|
||||
no.push(name);
|
||||
}
|
||||
}
|
||||
if (yes.length == codecs.length) {
|
||||
mse.textContent = 'MSE supports ' + yes.join(', ');
|
||||
mse.style.color = 'green';
|
||||
} else {
|
||||
mse.textContent = 'MSE supports ' + yes.join(', ') + ' but not ' + no.join(', ');
|
||||
mse.style.color = 'orange';
|
||||
}
|
||||
} else {
|
||||
mse.textContent = 'MSE not supported';
|
||||
mse.style.color = 'red';
|
||||
}
|
||||
if (hls1.canPlayType('video/webm; codecs="vp8, vorbis"')) {
|
||||
webm.textContent = 'flat WebM VP8/Vorbis supported';
|
||||
webm.style.color = 'green';
|
||||
} else {
|
||||
webm.textContent = 'flat WebM VP8/Vorbis not supported';
|
||||
webm.style.color = 'red';
|
||||
}
|
||||
if (typeof WebAssembly == 'object') {
|
||||
wasm.textContent = 'WebAssembly supported';
|
||||
wasm.style.color = 'green';
|
||||
} else {
|
||||
wasm.textContent = 'no WebAssembly support';
|
||||
wasm.style.color = 'red';
|
||||
}
|
||||
</script>
|
||||
<script src=ogvjs-1.8.4/ogv.js></script>
|
||||
<!--
|
||||
<script src=video-js/alt/video.core.js></script>
|
||||
<script src=videojs-http-streaming.js></script>
|
||||
-->
|
||||
<script src="node_modules/video.js/dist/video.js"></script>
|
||||
|
||||
<script src=videojs-ogvjs.js></script>
|
||||
<script>
|
||||
var playerConfig = {
|
||||
responsive: true,
|
||||
controlBar: {
|
||||
volumePanel: {
|
||||
vertical: true,
|
||||
inline: false
|
||||
}
|
||||
},
|
||||
techOrder: [ 'html5' ],
|
||||
html5: {}
|
||||
};
|
||||
|
||||
function can(mime) {
|
||||
return (typeof MediaSource == 'function') && MediaSource.isTypeSupported(mime);
|
||||
}
|
||||
var vp9 = can('video/mp4; codecs="vp09.00.10.08"');
|
||||
var opus = can('audio/mp4; codecs="opus"');
|
||||
var aac = can('audio/mp4; codecs="mp4a.40.02');
|
||||
var mp3 = can('audio/mp3');
|
||||
//var mp3 = can('audio/mp4; codecs="mp4a.40.34"');
|
||||
var mse = vp9 && (opus || mp3);
|
||||
if (mse) {
|
||||
// enable streaming plugin
|
||||
playerConfig.html5 = {
|
||||
vhs: {
|
||||
overrideNative: true,
|
||||
useDevicePixelRatio: true
|
||||
},
|
||||
nativeAudioTracks: false,
|
||||
nativeVideoTracks: false
|
||||
};
|
||||
console.log('will do mse');
|
||||
} else {
|
||||
console.log('wont do mse');
|
||||
}
|
||||
|
||||
var webm = null;
|
||||
var m3u8 = null;
|
||||
for (let source of hls1.querySelectorAll('source')) {
|
||||
if (source.type.startsWith('video/webm')) {
|
||||
webm = source;
|
||||
continue;
|
||||
}
|
||||
if (source.type == 'application/vnd.apple.mpegurl') {
|
||||
m3u8 = source;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var ogv = webm &&
|
||||
!mse &&
|
||||
!hls1.canPlayType(webm.type) &&
|
||||
(typeof WebAssembly == 'object') &&
|
||||
(typeof WebAssembly.Module == 'function');
|
||||
if (ogv) {
|
||||
console.log('can do ogvjs');
|
||||
var base = '/misc/hls-test/ogvjs-1.8.4';//new URL('./ogvjs-1.8.4', document.location.pathname)
|
||||
playerConfig.ogvjs = {
|
||||
base: base
|
||||
};
|
||||
console.log(playerConfig.ogvjs.base);
|
||||
playerConfig.techOrder.push('ogvjs');
|
||||
} else {
|
||||
console.log('wont do ogvjs');
|
||||
}
|
||||
|
||||
videojs.log.level('debug');
|
||||
|
||||
hls1.classList.add('video-js');
|
||||
hls1.classList.add('vjs-default-skin');
|
||||
var vjs1 = videojs(hls1, playerConfig);
|
||||
|
||||
vjs1.on('error', function failover() {
|
||||
console.log('got error');
|
||||
var error = vjs1.error();
|
||||
if (error && error.code == MediaError.MEDIA_ERR_DECODE) {
|
||||
console.log('saw its a decode error');
|
||||
// HLS reports this if it can't find a codec it likes
|
||||
console.log(m3u8);
|
||||
if (mse && m3u8) {
|
||||
console.log('going to m3u8: ' + m3u8.getAttribute('src'));
|
||||
vjs1.src([{
|
||||
src: m3u8.getAttribute('src'),
|
||||
type: m3u8.getAttribute('type')
|
||||
}]);
|
||||
vjs1.reset();
|
||||
m3u8 = null;
|
||||
} else if (webm) {
|
||||
console.log('going to webm: ' + webm.getAttribute('src'));
|
||||
vjs1.src([{
|
||||
src: webm.getAttribute('src'),
|
||||
type: webm.getAttribute('type')
|
||||
}]);
|
||||
vjs1.reset();
|
||||
webm = null;
|
||||
}
|
||||
}
|
||||
vjs1.off('error', failover);
|
||||
});
|
||||
|
||||
// this fails on Chrome with a blob issue on the HLS player :D
|
||||
//vjs1.load();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
231
ogv-vorbis.html
Normal file
231
ogv-vorbis.html
Normal file
|
@ -0,0 +1,231 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>HLS WebM test</title>
|
||||
<link rel=stylesheet type=text/css href=video-js/video-js.css>
|
||||
</head>
|
||||
<body>
|
||||
<h1>HLS WebM test</h1>
|
||||
|
||||
<p id=hls>Checking HLS support...</p>
|
||||
<p id=mse>Checking MSE VP9 support...</p>
|
||||
<p id=webm>Checking flat WebM VP8 / Vorbis support...</p>
|
||||
<p id=wasm>Checking WebAssembly support...</p>
|
||||
|
||||
<h2>Caminandes - Llamigos</h2>
|
||||
|
||||
<p>HLS with VP9-in-MP4 video and Vorbis-in-WebM or MP3 audio. Flat WebM fallback with ogv.js loader.</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-vorbis-mp3.m3u8>
|
||||
<source type="video/webm; codecs="vp8, vorbis"" src=caminandes-llamigos.webm.flat.webm>
|
||||
<source type="video/quicktime; codecs="jpeg, mp3"" src=polyphon-jpeg-mp3.mov>
|
||||
</video>
|
||||
|
||||
<p>Desired behavior:</p>
|
||||
<ul>
|
||||
<li>Firefox/Chrome: play via MSE with VP9/Opus (working)</li>
|
||||
<li>Desktop Safari with VP9 support: play via MSE with VP9/AAC or MP3 (currently MP3 fails)</li>
|
||||
<li>iOS Safari with VP9 support: play native HLS with VP9/AAC or MP3 (works)</li>
|
||||
<li>Older iOS and desktop Safari without VP9: play via ogv.js with WebM VP8/Vorbis (WebKit issue with some devices, in progress)</li>
|
||||
<li>Older iOS and desktop Safari without WebAssembly or with JS off: play backup MJPEG :D (HLS will take over but fail without JS)</li>
|
||||
<li>Very old Firefox/Chrome: play native WebM VP8/Vorbis</li>
|
||||
</ul>
|
||||
|
||||
<!--
|
||||
<p>HLS with VP9 video and Opus, AAC, and MP3 audio. Flag WebM fallback.</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-opus-aac-mp3.m3u8>
|
||||
<source type=video/webm src=caminandes-llamigos.webm.flat.webm>
|
||||
</video>
|
||||
|
||||
<p>Expected behavior:</p>
|
||||
<ul>
|
||||
<li>Firefox/Chrome: MSE VP9/Opus (AAC for now)</li>
|
||||
<li>Desktop Safari with VP9 support: MSE VP9/MP3 (AAC for now?)</li>
|
||||
<li>iOS Safari with VP9 support: HLS VP9/MP3 (AAC for now?)</li>
|
||||
<li>Older iOS and desktop Safari without VP9: ogv.js VP8/Vorbis</li>
|
||||
<li>Very old Firefox/Chrome: native WebM VP8/Vorbis</li>
|
||||
</ul>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<p>HLS with VP9 video and AAC audio. Flag WebM fallback.</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-aac.m3u8>
|
||||
<source type=video/webm src=caminandes-llamigos.webm.flat.webm>
|
||||
</video>
|
||||
|
||||
<p>Expected behavior:</p>
|
||||
<ul>
|
||||
<li>Firefox/Chrome: MSE VP9/Opus (AAC for now)</li>
|
||||
<li>Desktop Safari with VP9 support: MSE VP9/MP3 (AAC for now?)</li>
|
||||
<li>iOS Safari with VP9 support: HLS VP9/MP3 (AAC for now?)</li>
|
||||
<li>Older iOS and desktop Safari without VP9: ogv.js VP8/Vorbis</li>
|
||||
<li>Very old Firefox/Chrome: native WebM VP8/Vorbis</li>
|
||||
</ul>
|
||||
-->
|
||||
|
||||
<script>
|
||||
if (hls1.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
hls.textContent = 'native HLS playback supported';
|
||||
hls.style.color = 'green';
|
||||
} else {
|
||||
hls.textContent = 'no native HLS';
|
||||
hls.style.color = 'red';
|
||||
}
|
||||
if (typeof MediaSource == 'function') {
|
||||
let codecs = [
|
||||
['VP9-in-MP4', 'video/mp4; codecs="vp09.00.10.08"'],
|
||||
['Opus-in-WebM', 'audio/webm; codecs="opus"'],
|
||||
['MP3', 'audio/mp3'],
|
||||
];
|
||||
let yes = [];
|
||||
let no = [];
|
||||
for (let [name, mime] of codecs) {
|
||||
if (MediaSource.isTypeSupported(mime)) {
|
||||
yes.push(name);
|
||||
} else {
|
||||
no.push(name);
|
||||
}
|
||||
}
|
||||
if (yes.length == codecs.length) {
|
||||
mse.textContent = 'MSE supports ' + yes.join(', ');
|
||||
mse.style.color = 'green';
|
||||
} else {
|
||||
mse.textContent = 'MSE supports ' + yes.join(', ') + ' but not ' + no.join(', ');
|
||||
mse.style.color = 'orange';
|
||||
}
|
||||
} else {
|
||||
mse.textContent = 'MSE not supported';
|
||||
mse.style.color = 'red';
|
||||
}
|
||||
if (hls1.canPlayType('video/webm; codecs="vp8, vorbis"')) {
|
||||
webm.textContent = 'flat WebM VP8/Vorbis supported';
|
||||
webm.style.color = 'green';
|
||||
} else {
|
||||
webm.textContent = 'flat WebM VP8/Vorbis not supported';
|
||||
webm.style.color = 'red';
|
||||
}
|
||||
if (typeof WebAssembly == 'object') {
|
||||
wasm.textContent = 'WebAssembly supported';
|
||||
wasm.style.color = 'green';
|
||||
} else {
|
||||
wasm.textContent = 'no WebAssembly support';
|
||||
wasm.style.color = 'red';
|
||||
}
|
||||
</script>
|
||||
<script src=ogvjs-1.8.4/ogv.js></script>
|
||||
<!--
|
||||
<script src=video-js/alt/video.core.js></script>
|
||||
<script src=videojs-http-streaming.js></script>
|
||||
-->
|
||||
<script src="node_modules/video.js/dist/video.js"></script>
|
||||
|
||||
<script src=videojs-ogvjs.js></script>
|
||||
<script>
|
||||
var playerConfig = {
|
||||
responsive: true,
|
||||
controlBar: {
|
||||
volumePanel: {
|
||||
vertical: true,
|
||||
inline: false
|
||||
}
|
||||
},
|
||||
techOrder: [ 'html5' ],
|
||||
html5: {}
|
||||
};
|
||||
|
||||
function can(mime) {
|
||||
return (typeof MediaSource == 'function') && MediaSource.isTypeSupported(mime);
|
||||
}
|
||||
var vp9 = can('video/mp4; codecs="vp09.00.10.08"');
|
||||
var opus = can('audio/mp4; codecs="opus"');
|
||||
var aac = can('audio/mp4; codecs="mp4a.40.02');
|
||||
var mp3 = can('audio/mp3');
|
||||
//var mp3 = can('audio/mp4; codecs="mp4a.40.34"');
|
||||
var mse = vp9 && (opus || mp3);
|
||||
if (mse) {
|
||||
// enable streaming plugin
|
||||
playerConfig.html5 = {
|
||||
vhs: {
|
||||
overrideNative: true,
|
||||
useDevicePixelRatio: true
|
||||
},
|
||||
nativeAudioTracks: false,
|
||||
nativeVideoTracks: false
|
||||
};
|
||||
console.log('will do mse');
|
||||
} else {
|
||||
console.log('wont do mse');
|
||||
}
|
||||
|
||||
var webm = null;
|
||||
var m3u8 = null;
|
||||
for (let source of hls1.querySelectorAll('source')) {
|
||||
if (source.type.startsWith('video/webm')) {
|
||||
webm = source;
|
||||
continue;
|
||||
}
|
||||
if (source.type == 'application/vnd.apple.mpegurl') {
|
||||
m3u8 = source;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var ogv = webm &&
|
||||
!mse &&
|
||||
!hls1.canPlayType(webm.type) &&
|
||||
(typeof WebAssembly == 'object') &&
|
||||
(typeof WebAssembly.Module == 'function');
|
||||
if (ogv) {
|
||||
console.log('can do ogvjs');
|
||||
var base = '/misc/hls-test/ogvjs-1.8.4';//new URL('./ogvjs-1.8.4', document.location.pathname)
|
||||
playerConfig.ogvjs = {
|
||||
base: base
|
||||
};
|
||||
console.log(playerConfig.ogvjs.base);
|
||||
playerConfig.techOrder.push('ogvjs');
|
||||
} else {
|
||||
console.log('wont do ogvjs');
|
||||
}
|
||||
|
||||
videojs.log.level('debug');
|
||||
|
||||
hls1.classList.add('video-js');
|
||||
hls1.classList.add('vjs-default-skin');
|
||||
var vjs1 = videojs(hls1, playerConfig);
|
||||
|
||||
vjs1.on('error', function failover() {
|
||||
console.log('got error');
|
||||
var error = vjs1.error();
|
||||
if (error && error.code == MediaError.MEDIA_ERR_DECODE) {
|
||||
console.log('saw its a decode error');
|
||||
// HLS reports this if it can't find a codec it likes
|
||||
console.log(m3u8);
|
||||
if (mse && m3u8) {
|
||||
console.log('going to m3u8: ' + m3u8.getAttribute('src'));
|
||||
vjs1.src([{
|
||||
src: m3u8.getAttribute('src'),
|
||||
type: m3u8.getAttribute('type')
|
||||
}]);
|
||||
vjs1.reset();
|
||||
m3u8 = null;
|
||||
} else if (webm) {
|
||||
console.log('going to webm: ' + webm.getAttribute('src'));
|
||||
vjs1.src([{
|
||||
src: webm.getAttribute('src'),
|
||||
type: webm.getAttribute('type')
|
||||
}]);
|
||||
vjs1.reset();
|
||||
webm = null;
|
||||
}
|
||||
}
|
||||
vjs1.off('error', failover);
|
||||
});
|
||||
|
||||
// this fails on Chrome with a blob issue on the HLS player :D
|
||||
//vjs1.load();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
20
ogv.html
20
ogv.html
|
@ -15,10 +15,10 @@
|
|||
|
||||
<h2>Caminandes - Llamigos</h2>
|
||||
|
||||
<p>HLS with VP9-in-MP4 video and Opus-in-MP4, AAC-in-MP4, and MP3 audio. Flat WebM fallback with ogv.js loader.</p>
|
||||
<p>HLS with VP9-in-MP4 video with Opus-in-MP4 or MP3 audio. Flat WebM fallback with ogv.js loader.</p>
|
||||
<video id=hls1 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-opus-aac-mp3.m3u8>
|
||||
<!--<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3-opus.m3u8>-->
|
||||
<!--<source type=application/vnd.apple.mpegurl src=llamigos-vp9-opus-aac-mp3.m3u8>-->
|
||||
<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3-opus.m3u8>
|
||||
<!--<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3ts-opus.m3u8>-->
|
||||
<!--<source type=application/vnd.apple.mpegurl src=llamigos-vp9-mp3-vorbis.m3u8>-->
|
||||
<source type="video/webm; codecs="vp8, vorbis"" src=caminandes-llamigos.webm.flat.webm>
|
||||
|
@ -79,9 +79,13 @@
|
|||
}
|
||||
if (typeof MediaSource == 'function') {
|
||||
let codecs = [
|
||||
['VP9-in-MP4', 'video/mp4; codecs="vp09.00.10.08"'],
|
||||
['VP9-in-WebM', 'video/webm; codecs="vp9"'],
|
||||
['Opus-in-WebM', 'audio/webm; codecs="opus"'],
|
||||
['MP3', 'audio/mp3'],
|
||||
['Vorbis-in-WebM', 'audio/webm; codecs="vorbis"'],
|
||||
['VP9-in-MP4', 'video/mp4; codecs="vp09.00.10.08"'],
|
||||
['Opus-in-MP4', 'audio/mp4; codecs="opus"'],
|
||||
['MP3 (mp3)', 'audio/mp3'],
|
||||
['MP3 (mpeg)', 'audio/mpeg'],
|
||||
];
|
||||
let yes = [];
|
||||
let no = [];
|
||||
|
@ -123,8 +127,12 @@
|
|||
<script src=video-js/alt/video.core.js></script>
|
||||
<script src=videojs-http-streaming.js></script>
|
||||
-->
|
||||
<!--
|
||||
<script src="node_modules/video.js/dist/video.js"></script>
|
||||
|
||||
-->
|
||||
<script src="node_modules/video.js/dist/alt/video.core.js"></script>
|
||||
<script src="http-streaming/dist/videojs-http-streaming.js"></script>
|
||||
|
||||
<script src=videojs-ogvjs.js></script>
|
||||
<script>
|
||||
var playerConfig = {
|
||||
|
|
12
opus.html
12
opus.html
|
@ -25,6 +25,17 @@
|
|||
</video>
|
||||
<p id=err3></p>
|
||||
|
||||
<p>The video will try to load an HLS containing VP9-in-MP4 and fallback variants, with Opus audio marked as Opus also in the FOURCC:</p>
|
||||
<video id=hls4 controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=av-opusd-mp4.m3u8>
|
||||
</video>
|
||||
<p id=err4></p>
|
||||
|
||||
<p>Opus audio marked as opus in m3u and Opus in the FOURCC:</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=av-opuse-mp4.m3u8>
|
||||
</video>
|
||||
|
||||
<script>
|
||||
let codes = {
|
||||
[MediaError.MEDIA_ERR_ABORTED]: 'MEDIA_ERR_ABORTED',
|
||||
|
@ -42,6 +53,7 @@
|
|||
errify(hls1, err1);
|
||||
errify(hls2, err2);
|
||||
errify(hls3, err3);
|
||||
errify(hls4, err4);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
495
package-lock.json
generated
Normal file
495
package-lock.json
generated
Normal file
|
@ -0,0 +1,495 @@
|
|||
{
|
||||
"name": "hls-test",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "hls-test",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"video.js": "^7.21.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.18.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz",
|
||||
"integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@videojs/http-streaming": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.16.0.tgz",
|
||||
"integrity": "sha512-mGNTqjENzP86XGM6HSWdWVO/KAsDlf5+idW2W7dL1+NkzWpwZlSEYhrdEVVnhoOb0A6E7JW6LM611/JA7Jn/3A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "3.0.5",
|
||||
"aes-decrypter": "3.1.3",
|
||||
"global": "^4.4.0",
|
||||
"m3u8-parser": "4.8.0",
|
||||
"mpd-parser": "^0.22.1",
|
||||
"mux.js": "6.0.1",
|
||||
"video.js": "^6 || ^7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"video.js": "^6 || ^7"
|
||||
}
|
||||
},
|
||||
"node_modules/@videojs/vhs-utils": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz",
|
||||
"integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"global": "^4.4.0",
|
||||
"url-toolkit": "^2.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/@videojs/xhr": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.6.0.tgz",
|
||||
"integrity": "sha512-7J361GiN1tXpm+gd0xz2QWr3xNWBE+rytvo8J3KuggFaLg+U37gZQ2BuPLcnkfGffy2e+ozY70RHC8jt7zjA6Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"global": "~4.4.0",
|
||||
"is-function": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
"version": "0.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz",
|
||||
"integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aes-decrypter": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.3.tgz",
|
||||
"integrity": "sha512-VkG9g4BbhMBy+N5/XodDeV6F02chEk9IpgRTq/0bS80y4dzy79VH2Gtms02VXomf3HmyRe3yyJYkJ990ns+d6A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"global": "^4.4.0",
|
||||
"pkcs7": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-walk": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
||||
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/global": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"min-document": "^2.19.0",
|
||||
"process": "^0.11.10"
|
||||
}
|
||||
},
|
||||
"node_modules/individual": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/individual/-/individual-2.0.0.tgz",
|
||||
"integrity": "sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-function": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
|
||||
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/keycode": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz",
|
||||
"integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/m3u8-parser": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.8.0.tgz",
|
||||
"integrity": "sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"global": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/min-document": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
|
||||
"integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dom-walk": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mpd-parser": {
|
||||
"version": "0.22.1",
|
||||
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.22.1.tgz",
|
||||
"integrity": "sha512-fwBebvpyPUU8bOzvhX0VQZgSohncbgYwUyJJoTSNpmy7ccD2ryiCvM7oRkn/xQH5cv73/xU7rJSNCLjdGFor0Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"@xmldom/xmldom": "^0.8.3",
|
||||
"global": "^4.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"mpd-to-m3u8-json": "bin/parse.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mux.js": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-6.0.1.tgz",
|
||||
"integrity": "sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"global": "^4.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"muxjs-transmux": "bin/transmux.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/pkcs7": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz",
|
||||
"integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
},
|
||||
"bin": {
|
||||
"pkcs7": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/rust-result": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/rust-result/-/rust-result-1.0.0.tgz",
|
||||
"integrity": "sha1-NMdbLm3Dn+WHXlveyFteD5FTb3I=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"individual": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-json-parse": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-4.0.0.tgz",
|
||||
"integrity": "sha1-fA9XjPzNEtM6ccDgVBPi7KFx6qw=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"rust-result": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/url-toolkit": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.5.tgz",
|
||||
"integrity": "sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/video.js": {
|
||||
"version": "7.21.2",
|
||||
"resolved": "https://registry.npmjs.org/video.js/-/video.js-7.21.2.tgz",
|
||||
"integrity": "sha512-Zbo23oT4CbtIxeAtfTvzdl7OlN/P34ir7hDzXFtLZB+BtJsaLy0Rgh/06dBMJSGEjQCDo4MUS6uPonuX0Nl3Kg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/http-streaming": "2.16.0",
|
||||
"@videojs/vhs-utils": "^3.0.4",
|
||||
"@videojs/xhr": "2.6.0",
|
||||
"aes-decrypter": "3.1.3",
|
||||
"global": "^4.4.0",
|
||||
"keycode": "^2.2.0",
|
||||
"m3u8-parser": "4.8.0",
|
||||
"mpd-parser": "0.22.1",
|
||||
"mux.js": "6.0.1",
|
||||
"safe-json-parse": "4.0.0",
|
||||
"videojs-font": "3.2.0",
|
||||
"videojs-vtt.js": "^0.15.4"
|
||||
}
|
||||
},
|
||||
"node_modules/videojs-font": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz",
|
||||
"integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/videojs-vtt.js": {
|
||||
"version": "0.15.4",
|
||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz",
|
||||
"integrity": "sha512-r6IhM325fcLb1D6pgsMkTQT1PpFdUdYZa1iqk7wJEu+QlibBwATPfPc9Bg8Jiym0GE5yP1AG2rMLu+QMVWkYtA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"global": "^4.3.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.18.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz",
|
||||
"integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@videojs/http-streaming": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-2.16.0.tgz",
|
||||
"integrity": "sha512-mGNTqjENzP86XGM6HSWdWVO/KAsDlf5+idW2W7dL1+NkzWpwZlSEYhrdEVVnhoOb0A6E7JW6LM611/JA7Jn/3A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "3.0.5",
|
||||
"aes-decrypter": "3.1.3",
|
||||
"global": "^4.4.0",
|
||||
"m3u8-parser": "4.8.0",
|
||||
"mpd-parser": "^0.22.1",
|
||||
"mux.js": "6.0.1",
|
||||
"video.js": "^6 || ^7"
|
||||
}
|
||||
},
|
||||
"@videojs/vhs-utils": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz",
|
||||
"integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"global": "^4.4.0",
|
||||
"url-toolkit": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"@videojs/xhr": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.6.0.tgz",
|
||||
"integrity": "sha512-7J361GiN1tXpm+gd0xz2QWr3xNWBE+rytvo8J3KuggFaLg+U37gZQ2BuPLcnkfGffy2e+ozY70RHC8jt7zjA6Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"global": "~4.4.0",
|
||||
"is-function": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@xmldom/xmldom": {
|
||||
"version": "0.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz",
|
||||
"integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==",
|
||||
"dev": true
|
||||
},
|
||||
"aes-decrypter": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.1.3.tgz",
|
||||
"integrity": "sha512-VkG9g4BbhMBy+N5/XodDeV6F02chEk9IpgRTq/0bS80y4dzy79VH2Gtms02VXomf3HmyRe3yyJYkJ990ns+d6A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"global": "^4.4.0",
|
||||
"pkcs7": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"dom-walk": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
||||
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==",
|
||||
"dev": true
|
||||
},
|
||||
"global": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"min-document": "^2.19.0",
|
||||
"process": "^0.11.10"
|
||||
}
|
||||
},
|
||||
"individual": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/individual/-/individual-2.0.0.tgz",
|
||||
"integrity": "sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==",
|
||||
"dev": true
|
||||
},
|
||||
"is-function": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
|
||||
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==",
|
||||
"dev": true
|
||||
},
|
||||
"keycode": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz",
|
||||
"integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==",
|
||||
"dev": true
|
||||
},
|
||||
"m3u8-parser": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.8.0.tgz",
|
||||
"integrity": "sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"global": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"min-document": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
|
||||
"integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dom-walk": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"mpd-parser": {
|
||||
"version": "0.22.1",
|
||||
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.22.1.tgz",
|
||||
"integrity": "sha512-fwBebvpyPUU8bOzvhX0VQZgSohncbgYwUyJJoTSNpmy7ccD2ryiCvM7oRkn/xQH5cv73/xU7rJSNCLjdGFor0Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/vhs-utils": "^3.0.5",
|
||||
"@xmldom/xmldom": "^0.8.3",
|
||||
"global": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"mux.js": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-6.0.1.tgz",
|
||||
"integrity": "sha512-22CHb59rH8pWGcPGW5Og7JngJ9s+z4XuSlYvnxhLuc58cA1WqGDQPzuG8I+sPm1/p0CdgpzVTaKW408k5DNn8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"global": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"pkcs7": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz",
|
||||
"integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
|
||||
"dev": true
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
|
||||
"dev": true
|
||||
},
|
||||
"rust-result": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/rust-result/-/rust-result-1.0.0.tgz",
|
||||
"integrity": "sha1-NMdbLm3Dn+WHXlveyFteD5FTb3I=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"individual": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"safe-json-parse": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-4.0.0.tgz",
|
||||
"integrity": "sha1-fA9XjPzNEtM6ccDgVBPi7KFx6qw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"rust-result": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"url-toolkit": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.5.tgz",
|
||||
"integrity": "sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==",
|
||||
"dev": true
|
||||
},
|
||||
"video.js": {
|
||||
"version": "7.21.2",
|
||||
"resolved": "https://registry.npmjs.org/video.js/-/video.js-7.21.2.tgz",
|
||||
"integrity": "sha512-Zbo23oT4CbtIxeAtfTvzdl7OlN/P34ir7hDzXFtLZB+BtJsaLy0Rgh/06dBMJSGEjQCDo4MUS6uPonuX0Nl3Kg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@videojs/http-streaming": "2.16.0",
|
||||
"@videojs/vhs-utils": "^3.0.4",
|
||||
"@videojs/xhr": "2.6.0",
|
||||
"aes-decrypter": "3.1.3",
|
||||
"global": "^4.4.0",
|
||||
"keycode": "^2.2.0",
|
||||
"m3u8-parser": "4.8.0",
|
||||
"mpd-parser": "0.22.1",
|
||||
"mux.js": "6.0.1",
|
||||
"safe-json-parse": "4.0.0",
|
||||
"videojs-font": "3.2.0",
|
||||
"videojs-vtt.js": "^0.15.4"
|
||||
}
|
||||
},
|
||||
"videojs-font": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-3.2.0.tgz",
|
||||
"integrity": "sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==",
|
||||
"dev": true
|
||||
},
|
||||
"videojs-vtt.js": {
|
||||
"version": "0.15.4",
|
||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.4.tgz",
|
||||
"integrity": "sha512-r6IhM325fcLb1D6pgsMkTQT1PpFdUdYZa1iqk7wJEu+QlibBwATPfPc9Bg8Jiym0GE5yP1AG2rMLu+QMVWkYtA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"global": "^4.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
package.json
Normal file
17
package.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "hls-test",
|
||||
"version": "1.0.0",
|
||||
"description": "test test test",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"example": "examples"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "false"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"video.js": "^7.21.2"
|
||||
}
|
||||
}
|
7
run-llamigos.sh
Normal file
7
run-llamigos.sh
Normal file
|
@ -0,0 +1,7 @@
|
|||
# exit when any command fails
|
||||
set -e
|
||||
|
||||
# create caminandes-llamigos.webm.audio.mp3.combined.m3u8
|
||||
# and caminandes-llamigos.webm.audio.mp3
|
||||
php timestamp-id3.php
|
||||
|
29
sizes.js
Normal file
29
sizes.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
let heights = [
|
||||
120,
|
||||
180,
|
||||
240,
|
||||
360,
|
||||
480,
|
||||
720,
|
||||
1080,
|
||||
1440,
|
||||
2160
|
||||
];
|
||||
|
||||
let base = 480;
|
||||
let bitrate = 1000;
|
||||
let exponent = 0.85;
|
||||
|
||||
function area(h) {
|
||||
let w = Math.round(h * 16 / 9);
|
||||
return w * h;
|
||||
}
|
||||
|
||||
function rate(h) {
|
||||
let ratio = area(h) / area(base);
|
||||
return Math.round(bitrate * (ratio ** exponent));
|
||||
}
|
||||
|
||||
for (let h of heights) {
|
||||
console.log(`${h}: ${rate(h)}`);
|
||||
}
|
7
standalone-mjpeg-aac-mov.m3u8
Normal file
7
standalone-mjpeg-aac-mov.m3u8
Normal file
|
@ -0,0 +1,7 @@
|
|||
#EXTM3U
|
||||
#EXT-X-VERSION:7
|
||||
#EXT-X-TARGETDURATION:150
|
||||
#EXT-X-MEDIA-SEQUENCE:0
|
||||
#EXT-X-PLAYLIST-TYPE:VOD
|
||||
#EXTINF:150.04,
|
||||
standalone-mjpeg-mp3.mov
|
7
standalone-mjpeg-mov.m3u8
Normal file
7
standalone-mjpeg-mov.m3u8
Normal file
|
@ -0,0 +1,7 @@
|
|||
#EXTM3U
|
||||
#EXT-X-VERSION:7
|
||||
#EXT-X-TARGETDURATION:150
|
||||
#EXT-X-MEDIA-SEQUENCE:0
|
||||
#EXT-X-PLAYLIST-TYPE:VOD
|
||||
#EXTINF:150.04,
|
||||
standalone-mjpeg.mov
|
7
standalone-mjpeg-mp3-mov.m3u8
Normal file
7
standalone-mjpeg-mp3-mov.m3u8
Normal file
|
@ -0,0 +1,7 @@
|
|||
#EXTM3U
|
||||
#EXT-X-VERSION:7
|
||||
#EXT-X-TARGETDURATION:150
|
||||
#EXT-X-MEDIA-SEQUENCE:0
|
||||
#EXT-X-PLAYLIST-TYPE:VOD
|
||||
#EXTINF:150.04,
|
||||
standalone-mjpeg-mp3.mov
|
28
standalone.html
Normal file
28
standalone.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>HLS VP9/fMP4 test</title>
|
||||
<link rel=stylesheet type=text/css href=video-js/video-js.css>
|
||||
</head>
|
||||
<body>
|
||||
<h1>iOS HLS VP9 fallback test</h1>
|
||||
|
||||
<p>WebM VP9/Opus and VP8/Vorbis with fallback HLS with VP9-and-AAC-in-fMP4.</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/webm; codecs="vp9, opus"" src=standalone-vp9.webm>
|
||||
<source type="video/webm; codecs="vp8, vorbis"" src=standalone-vp8.webm>
|
||||
<source type=application/vnd.apple.mpegurl src=standalone-vp9-aac.m3u8>
|
||||
</video>
|
||||
|
||||
<p>Only HLS with VP9-and-AAC-in-fMP4.</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type=application/vnd.apple.mpegurl src=standalone-vp9-aac.m3u8>
|
||||
</video>
|
||||
|
||||
<p>Direct VP9-and-AAC-in-fMP4.</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/mp4" src=standalone-vp9-aac.mp4>
|
||||
</video>
|
||||
</body>
|
||||
</html>
|
|
@ -387,10 +387,9 @@ $infiles = [
|
|||
foreach ( $infiles as $filename ) {
|
||||
$source = new SourceFile( $filename );
|
||||
$codec = new Transcoder( $source );
|
||||
//$codec->audio('aac');
|
||||
//$codec->audio('opus');
|
||||
$codec->audio('vorbis.webm');
|
||||
/*
|
||||
$codec->audio('aac');
|
||||
$codec->audio('opus');
|
||||
//$codec->audio('vorbis.webm');
|
||||
$codec->audio('mp3');
|
||||
$codec->audio('mp3.ts');
|
||||
$codec->audio('mp3.mp4');
|
||||
|
@ -408,5 +407,4 @@ foreach ( $infiles as $filename ) {
|
|||
$codec->video('vp9', $res, 'pass2');
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
410
transcode-segment2.php
Normal file
410
transcode-segment2.php
Normal file
|
@ -0,0 +1,410 @@
|
|||
<?php
|
||||
|
||||
function run( $prog, $params ) {
|
||||
$cmd = escapeshellcmd( $prog ) . " " . implode( ' ', array_map( 'escapeshellarg', $params ) );
|
||||
echo "\n$cmd\n\n";
|
||||
$output = [];
|
||||
$code = 0;
|
||||
if ( exec($cmd, $output, $code) === false ) {
|
||||
throw new Exception( 'failed to exec ffmpeg' );
|
||||
}
|
||||
if ( $code ) {
|
||||
throw new Exception( "ffmpeg returned coded $code" );
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
function ffprobe( $file ) {
|
||||
$output = run( 'ffprobe', [ '-hide_banner', '-show_format', '-show_streams', '-print_format', 'json', '--', $file ] );
|
||||
$json = implode( "\n", $output );
|
||||
return json_decode( $json );
|
||||
}
|
||||
|
||||
class Audio {
|
||||
public const FORMATS = [
|
||||
'aac' => [
|
||||
'container' => 'mp4',
|
||||
'options' => [
|
||||
'-acodec', 'aac',
|
||||
'-ar', 44100,
|
||||
'-ac', 2,
|
||||
'-b:a', '112k',
|
||||
],
|
||||
],
|
||||
'opus' => [
|
||||
'container' => 'mp4',
|
||||
'options' => [
|
||||
'-acodec', 'libopus',
|
||||
'-ar', 48000,
|
||||
'-ac', 2,
|
||||
'-b:a', '96k',
|
||||
],
|
||||
],
|
||||
'vorbis.webm' => [
|
||||
'container' => 'webm',
|
||||
'options' => [
|
||||
'-acodec', 'libvorbis',
|
||||
'-b:a', '112k',
|
||||
],
|
||||
],
|
||||
// with the added id3 timestamps this work great with iOS HLS
|
||||
// but mac safari doesn't seem happy with anything i do with them
|
||||
'mp3' => [
|
||||
'container' => 'mp3',
|
||||
'options' => [
|
||||
'-acodec', 'libmp3lame',
|
||||
'-ar', 44100,
|
||||
'-ac', 2,
|
||||
'-b:a', '128k',
|
||||
],
|
||||
],
|
||||
// works on iOS HLS but seems stuttery? i dunno why
|
||||
// mac safari doesn't seem to like it either
|
||||
'mp3.ts' => [
|
||||
'container' => 'ts',
|
||||
'options' => [
|
||||
'-acodec', 'libmp3lame',
|
||||
'-ar', 44100,
|
||||
'-ac', 2,
|
||||
'-b:a', '128k',
|
||||
],
|
||||
],
|
||||
// no dice on ios or macos safari
|
||||
'mp3.mp4' => [
|
||||
'container' => 'mp4',
|
||||
'options' => [
|
||||
'-acodec', 'libmp3lame',
|
||||
'-ar', 44100,
|
||||
'-ac', 2,
|
||||
'-b:a', '128k',
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
class Video {
|
||||
// Normalize input frame rates to the next up of these.
|
||||
// Lets us ensure that keyframes are places where they belong.
|
||||
public const RATES = [
|
||||
15, 24, 25, 30, 48, 50, 60
|
||||
];
|
||||
|
||||
public const FORMATS = [
|
||||
'mjpeg' => [
|
||||
// it doesn't seem to like this after all. worth trying!
|
||||
'container' => 'mov',
|
||||
'options' => [
|
||||
'common' => [
|
||||
'-vcodec', 'mjpeg',
|
||||
],
|
||||
'fallback' => [
|
||||
// no specific options :D
|
||||
],
|
||||
],
|
||||
'resolutions' => [
|
||||
'144p' => [
|
||||
'width' => 176,
|
||||
'height' => 144,
|
||||
'bitrate' => '1024k',
|
||||
]
|
||||
]
|
||||
],
|
||||
'vp9' => [
|
||||
'container' => 'mp4',
|
||||
'options' => [
|
||||
'common' => [
|
||||
'-vcodec', 'libvpx-vp9',
|
||||
'-row-mt', '1',
|
||||
'-tile-columns', '4',
|
||||
],
|
||||
'fast' => [
|
||||
'-quality', 'realtime',
|
||||
'-cpu-used', '5',
|
||||
],
|
||||
'pass1' => [
|
||||
'-quality', 'good',
|
||||
'-cpu-used', '2',
|
||||
'-pass', '1',
|
||||
],
|
||||
'pass2' => [
|
||||
'-quality', 'good',
|
||||
'-cpu-used', '1',
|
||||
'-pass', '2',
|
||||
]
|
||||
],
|
||||
'resolutions' => [
|
||||
'240p' => [
|
||||
'width' => 426,
|
||||
'height' => 240,
|
||||
'bitrate' => '150k',
|
||||
],
|
||||
'360p' => [
|
||||
'width' => 640,
|
||||
'height' => 360,
|
||||
'bitrate' => '250k',
|
||||
],
|
||||
'480p' => [
|
||||
'width' => 854,
|
||||
'height' => 480,
|
||||
'bitrate' => '750k',
|
||||
],
|
||||
'720p' => [
|
||||
'width' => 1280,
|
||||
'height' => 720,
|
||||
'bitrate' => '2500k',
|
||||
],
|
||||
'1080p' => [
|
||||
'width' => 1920,
|
||||
'height' => 1080,
|
||||
'bitrate' => '5000k',
|
||||
],
|
||||
'1440p' => [
|
||||
'width' => 2560,
|
||||
'height' => 1440,
|
||||
'bitrate' => '9000k',
|
||||
],
|
||||
'2160p' => [
|
||||
'width' => 3840,
|
||||
'height' => 2160,
|
||||
'bitrate' => '12500k',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
class Fraction {
|
||||
public $numerator = 0;
|
||||
public $denominator = 0;
|
||||
|
||||
public function __construct( $num, $denom ) {
|
||||
$this->numerator = $num;
|
||||
$this->denominator = $denom;
|
||||
}
|
||||
|
||||
public function toFloat() {
|
||||
return $this->numerator / $this->denominator;
|
||||
}
|
||||
|
||||
public function toString() {
|
||||
return "$this->numerator/$this->denominator";
|
||||
}
|
||||
|
||||
public static function fromString( $frac ) {
|
||||
list ( $num, $denom ) = array_map( 'intval', explode( '/', $frac, 2 ) );
|
||||
return new Fraction( $num, $denom );
|
||||
}
|
||||
}
|
||||
|
||||
class SourceFile {
|
||||
public $filename = '';
|
||||
public $duration = 0.0;
|
||||
|
||||
public $video = false;
|
||||
public $width = 0;
|
||||
public $height = 0;
|
||||
public $fps = null;
|
||||
|
||||
public $audio = false;
|
||||
public $sampleRate = 0;
|
||||
public $channels = 0;
|
||||
|
||||
public function __construct( $filename ) {
|
||||
$this->filename = $filename;
|
||||
|
||||
$data = ffprobe( $filename );
|
||||
|
||||
$this->duration = $data->format->duration;
|
||||
foreach ( $data->streams as $stream ) {
|
||||
if ( $stream->codec_type == 'video' && !$this->video ) {
|
||||
$this->video = true;
|
||||
$this->width = $stream->width;
|
||||
$this->height = $stream->height;
|
||||
$this->fps = Fraction::fromString( $stream->r_frame_rate );
|
||||
}
|
||||
if ( $stream->codec_type === 'audio' && !$this->audio ) {
|
||||
$this->audio = true;
|
||||
$this->sampleRate = $stream->sample_rate;
|
||||
$this->channels = $stream->channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Transcoder {
|
||||
private $source = null;
|
||||
private $fps = 0;
|
||||
private $gop = 0;
|
||||
|
||||
public const SEGMENT_DURATION = 10;
|
||||
|
||||
public function __construct( SourceFile $source ) {
|
||||
$this->source = $source;
|
||||
|
||||
// Normalize input fps to an even standard
|
||||
$infps = $this->source->fps->toFloat();
|
||||
$this->fps = Video::RATES[0];
|
||||
foreach ( Video::RATES as $rate ) {
|
||||
if ( $rate >= $infps ) {
|
||||
$this->fps = $rate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Each self-contained group of pictures starts with a keyframe.
|
||||
$this->gop = $this->fps * self::SEGMENT_DURATION;
|
||||
}
|
||||
|
||||
private function ffmpeg( $options, $outfile, $container ) {
|
||||
$playlist = "$outfile.m3u8";
|
||||
$init = "$outfile.init.$container";
|
||||
if ( $container == 'mp4' ) {
|
||||
// HLS muxer seems to give the right options for fMP4
|
||||
$segment = "$outfile.$container";
|
||||
$segmentOptions = [
|
||||
'-f', 'hls',
|
||||
'-hls_segment_type', 'fmp4',
|
||||
'-hls_flags', 'single_file',
|
||||
'-hls_time', '10',
|
||||
'-hls_playlist_type', 'vod',
|
||||
'-hls_fmp4_init_filename', $init,
|
||||
'-hls_segment_filename', $segment,
|
||||
'-y', $playlist,
|
||||
];
|
||||
} elseif ( $container == 'ts' ) {
|
||||
$segment = "$outfile.$container";
|
||||
$segmentOptions = [
|
||||
'-f', 'hls',
|
||||
'-hls_segment_type', 'mpegts',
|
||||
'-hls_flags', 'single_file',
|
||||
'-hls_time', '10',
|
||||
'-hls_playlist_type', 'vod',
|
||||
'-hls_segment_filename', $segment,
|
||||
'-y', $playlist,
|
||||
];
|
||||
} elseif ( $container == 'webm' ) {
|
||||
$segment = "$outfile.%04d.$container";
|
||||
$segmentOptions = [
|
||||
'-f', 'segment',
|
||||
'-segment_time', '10',
|
||||
'-segment_list', $playlist,
|
||||
'-y', $segment
|
||||
];
|
||||
} elseif ( $container == 'mov' ) {
|
||||
// For MJPEG, MP4 doesn't work in Apple HLS for some reason
|
||||
// but QuickTime is sortof ok for one segment?
|
||||
// Note segment won't make single fMP4-style files though.
|
||||
$segment = "$outfile.%04d.$container";
|
||||
$segmentOptions = [
|
||||
'-f', 'segment',
|
||||
//'-segment_format_options', 'movflags=frag_keyframe+empty_moov',
|
||||
//'-segment_format_options', 'movflags=+frag_keyframe+empty_moov+default_base_moof+faststart',
|
||||
'-segment_time', '10',
|
||||
'-segment_list', $playlist,
|
||||
'-y', $segment
|
||||
];
|
||||
} elseif ( $container == 'mp3' ) {
|
||||
// For MP3, segment it raw.
|
||||
// We'll need to postprocess to add an ID3 tag with timestamp
|
||||
// and to reassemble into a file with byte ranges.
|
||||
$segment = "$outfile.%04d.$container";
|
||||
$segmentOptions = [
|
||||
'-f', 'segment',
|
||||
'-segment_format_options', 'id3v2_version=0:write_xing=0:write_id3v1=0',
|
||||
'-segment_time', '10',
|
||||
'-segment_list', $playlist,
|
||||
'-y', $segment
|
||||
];
|
||||
} else {
|
||||
die( 'missing container in config' );
|
||||
}
|
||||
$ffmpegOptions = array_merge( [
|
||||
'-hide_banner',
|
||||
'-i', $this->source->filename,
|
||||
], $options, $segmentOptions);
|
||||
|
||||
$output = run( 'ffmpeg', $ffmpegOptions );
|
||||
}
|
||||
|
||||
public function video( $codec, $resolution, $mode ) {
|
||||
if ( !$this->source->video ) {
|
||||
throw new Error('no video');
|
||||
}
|
||||
|
||||
$format = Video::FORMATS[$codec];
|
||||
$res = $format['resolutions'][$resolution];
|
||||
|
||||
$options = array_merge(
|
||||
[
|
||||
'-pix_fmt', 'yuv420p',
|
||||
'-r', $this->fps,
|
||||
],
|
||||
$format['options']['common'],
|
||||
$format['options'][$mode],
|
||||
[
|
||||
'-vf', "scale=" . implode( ':', [ $res['width'], $res['height'] ] ),
|
||||
'-b:v', $res['bitrate'],
|
||||
'-g', $this->gop,
|
||||
'-keyint_min', $this->gop, // may not be generic enough
|
||||
'-an',
|
||||
]
|
||||
);
|
||||
|
||||
$this->ffmpeg(
|
||||
$options,
|
||||
"{$this->source->filename}.{$resolution}.{$codec}.{$mode}",
|
||||
$format['container']
|
||||
);
|
||||
}
|
||||
|
||||
public function audio( $codec ) {
|
||||
if ( !$this->source->audio ) {
|
||||
throw new Error('no audio');
|
||||
}
|
||||
|
||||
$format = Audio::FORMATS[$codec];
|
||||
$options = array_merge(
|
||||
$format['options'],
|
||||
[
|
||||
'-vn',
|
||||
]
|
||||
);
|
||||
|
||||
$this->ffmpeg(
|
||||
$options,
|
||||
"{$this->source->filename}.audio.{$codec}",
|
||||
$format['container']
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$infiles = [
|
||||
'caminandes-llamigos.webm',
|
||||
];
|
||||
|
||||
foreach ( $infiles as $filename ) {
|
||||
$source = new SourceFile( $filename );
|
||||
$codec = new Transcoder( $source );
|
||||
$codec->audio('aac');
|
||||
$codec->audio('opus');
|
||||
//$codec->audio('vorbis.webm');
|
||||
$codec->audio('mp3');
|
||||
$codec->audio('mp3.ts');
|
||||
$codec->audio('mp3.mp4');
|
||||
foreach ( Video::FORMATS['mjpeg']['resolutions'] as $res => $format ) {
|
||||
$codec->video('mjpeg', $res, 'fallback');
|
||||
}
|
||||
foreach ( Video::FORMATS['vp9']['resolutions'] as $res => $format ) {
|
||||
if ( $format['width'] <= $source->width && $format['height'] <= $source->height ) {
|
||||
$codec->video('vp9', $res, 'fast');
|
||||
}
|
||||
}
|
||||
foreach ( Video::FORMATS['vp9']['resolutions'] as $res => $format ) {
|
||||
if ( $format['width'] <= $source->width && $format['height'] <= $source->height ) {
|
||||
$codec->video('vp9', $res, 'pass1');
|
||||
$codec->video('vp9', $res, 'pass2');
|
||||
}
|
||||
}
|
||||
}
|
19
vp8.html
19
vp8.html
|
@ -8,30 +8,35 @@
|
|||
<h1>Flat WebM test</h1>
|
||||
|
||||
<p>WebM VP8/Vorbis marked as such:</p>
|
||||
<video id=flat1 controls width=640 height=360>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/webm; codecs="vp8, vorbis"" src=polyphon-vp8-vorbis.webm>
|
||||
</video>
|
||||
|
||||
<p>WebM VP8/Vorbis unmarked:</p>
|
||||
<video id=flat2 controls width=640 height=360 src=polyphon-vp8-vorbis.webm>
|
||||
<video controls width=640 height=360 src=polyphon-vp8-vorbis.webm>
|
||||
</video>
|
||||
|
||||
<p>WebM VP8 (no audio) marked as such:</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/webm; codecs="vp8"" src=polyphon-vp8.webm>
|
||||
</video>
|
||||
|
||||
<p>WebM VP8 (no audio) unmarked:</p>
|
||||
<video id=flat3 controls width=640 height=360 src=polyphon-vp8.webm>
|
||||
<video controls width=640 height=360 src=polyphon-vp8.webm>
|
||||
</video>
|
||||
|
||||
<p>MP4 VP8 (no audio), marked as vp8:</p>
|
||||
<video id=flat4 controls width=640 height=360>
|
||||
<p>MP4 VP8 (no audio), marked as vp8 (expected to fail):</p>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/mp4; codecs="vp8"" src=polyphon-vp8.mp4>
|
||||
</video>
|
||||
|
||||
<p>MP4 VP8 (no audio), marked as vp08:</p>
|
||||
<video id=flat5 controls width=640 height=360>
|
||||
<video controls width=640 height=360>
|
||||
<source type="video/mp4; codecs="vp08"" src=polyphon-vp8.mp4>
|
||||
</video>
|
||||
|
||||
<p>MP4 VP8 (no audio), unmarked:</p>
|
||||
<video id=flat6 controls width=640 height=360 src=polyphon-vp8.mp4>
|
||||
<video controls width=640 height=360 src=polyphon-vp8.mp4>
|
||||
</video>
|
||||
|
||||
</body>
|
||||
|
|
Loading…
Reference in a new issue