WaveSurfer player voor podcasts, voor live WIP
This commit is contained in:
@@ -186,6 +186,7 @@
|
||||
<script type="text/javascript" src="/js/jquery.prettyPhoto.js"></script>
|
||||
<script type="text/javascript" src="/js/jquery.carouFredSel-6.2.1.min.js"></script>
|
||||
<script type="text/javascript" src="/js/functions.js"></script>
|
||||
<script type="text/javascript" src="/js/wavesurfer.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(window).resize(function () {
|
||||
// Fix sticky for mobile menu indicator
|
||||
|
||||
@@ -36,9 +36,15 @@
|
||||
</p>
|
||||
@endif
|
||||
<p>
|
||||
<audio controls autoplay="true">
|
||||
{{-- <audio controls autoplay="true">
|
||||
<source src="{{$source}}" type="audio/mp3"/>
|
||||
</audio>
|
||||
</audio> --}}
|
||||
|
||||
@include('widgets.audioplayer', [
|
||||
'source' =>str_replace("stream", "download", $source),
|
||||
'lengte' => 0,
|
||||
'waveform' => []
|
||||
])
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -130,6 +136,7 @@
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript" src="/js/jquery-3.7.1.min.js"></script>
|
||||
<script type="text/javascript" src="/js/wavesurfer.min.js"></script>
|
||||
<script>
|
||||
function updateOnAir() {
|
||||
$.ajax({
|
||||
@@ -163,4 +170,3 @@
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@include('widgets.mediaplayer')
|
||||
|
||||
@@ -88,11 +88,11 @@
|
||||
|
||||
@section('content')
|
||||
@if ($podcast)
|
||||
<?php
|
||||
<?php
|
||||
$audioUrl = url($apiUrl . 'podcast/download' . $podcast->url . "?auth=" . $podcast->auth);
|
||||
$streamUrl = url($apiUrl . 'podcast/stream' . $podcast->url . "?auth=" . $podcast->auth);
|
||||
$popoutUrl = route('luister.podcast') . $podcast->url . '?auth=' . $podcast->auth;
|
||||
?>
|
||||
?>
|
||||
|
||||
<div class="">
|
||||
<div class="row news_post">
|
||||
@@ -112,9 +112,12 @@
|
||||
</ul>
|
||||
|
||||
<div class="announcement">
|
||||
<audio controls>
|
||||
<source src="{{$streamUrl}}" type="audio/mpeg"/>
|
||||
</audio>
|
||||
@include("widgets.audioplayer", [
|
||||
'source' => $streamUrl,
|
||||
'lengte' => $podcast->duration / 1000,
|
||||
'waveform' => $podcast->waveform
|
||||
])
|
||||
|
||||
<div class="clearfix">
|
||||
<a class="action_button btn" href="{{$audioUrl}}" title="Download dit fragment als MP3">
|
||||
<span>Download fragment</span>
|
||||
|
||||
213
resources/views/widgets/audioplayer.blade.php
Normal file
213
resources/views/widgets/audioplayer.blade.php
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php $id = uniqid('player_'); ?>
|
||||
<div class="audioplayer" id="{{ $id }}">
|
||||
{{--
|
||||
<label for="lengte" class="col-12 col-sm-2 col-form-label">Lengte</label>
|
||||
<div class="col-12 col-sm-10 my-auto">
|
||||
@if( $lengte > 60)
|
||||
{{ floor($lengte / 60) }} minuten en {{ floor(($lengte % 60)) }} seconden
|
||||
@else
|
||||
{{ $lengte }} seconden
|
||||
@endif
|
||||
</div>
|
||||
--}}
|
||||
|
||||
<div class="waveform">
|
||||
<div class="time">0:00</div>
|
||||
<div class="duration">0:00</div>
|
||||
<div class="hover"></div>
|
||||
</div>
|
||||
|
||||
<div class="volume-controls">
|
||||
<button class="btn-toggle-mute" type="button">
|
||||
<span class="fa fa-volume-high"></span>
|
||||
</button>
|
||||
<input class="volume-slider" type="range" min="0" max="1" step="0.01" value="1"
|
||||
onchange="wavesurfer_{{ $id }}.setVolume( this.value )" />
|
||||
</div>
|
||||
|
||||
<div class="audio-controls">
|
||||
<button class="btn btn-jump" type="button" onclick="wavesurfer_{{ $id }}.skip(-60)">
|
||||
<span class="fa fa-backward-fast"></span>
|
||||
<label>-60 s</label>
|
||||
</button>
|
||||
<button class="btn btn-jump" type="button" onclick="wavesurfer_{{ $id }}.skip(-10)">
|
||||
<span class="fa fa-backward-step"></span>
|
||||
<label>-10 s</label>
|
||||
</button>
|
||||
<button class="btn btn-play" type="button" onclick="wavesurfer_{{ $id }}.playPause()">
|
||||
<span class="play-button-icon fa fa-play"></span>
|
||||
<label class="play-button-label">Afspelen</label>
|
||||
</button>
|
||||
<button class="btn btn-jump" type="button" onclick="wavesurfer_{{ $id }}.skip(10)">
|
||||
<span class="fa fa-forward-step"></span>
|
||||
<label>+10 s</label>
|
||||
</button>
|
||||
<button class="btn btn-jump" type="button" onclick="wavesurfer_{{ $id }}.skip(60)">
|
||||
<span class="fa fa-forward-fast"></span>
|
||||
<label>+60 s</label>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var wavesurfer_{{ $id }};
|
||||
addEventListener("DOMContentLoaded", function() {
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
||||
// Create the waveform
|
||||
wavesurfer_{{ $id }} = WaveSurfer.create({
|
||||
container: '#{{ $id }} .waveform',
|
||||
waveColor: '#3A96EE',
|
||||
progressColor: '#0118A1',
|
||||
barWidth: 1,
|
||||
// duration: {{ $lengte }},
|
||||
// @if($waveform)
|
||||
// peaks: {{ json_encode($waveform->data) }},
|
||||
// normalize: true,
|
||||
// @endif
|
||||
|
||||
url: '{{ $source }}',
|
||||
});
|
||||
|
||||
// Play/pause on click
|
||||
wavesurfer_{{ $id }}.on('click', () => {
|
||||
wavesurfer_{{ $id }}.play();
|
||||
})
|
||||
wavesurfer_{{ $id }}.on('play', () => {
|
||||
$('#{{ $id }} .play-button-icon').addClass('fa-pause').removeClass('fa-play');
|
||||
$('#{{ $id }} .play-button-label').text('Pauzeren');
|
||||
})
|
||||
wavesurfer_{{ $id }}.on('pause', () => {
|
||||
$('#{{ $id }} .play-button-icon').addClass('fa-play').removeClass('fa-pause');
|
||||
$('#{{ $id }} .play-button-label').text('Verder spelen');
|
||||
})
|
||||
|
||||
$('#{{ $id }} .btn-toggle-mute').on('click', () => {
|
||||
var isMuted = !wavesurfer_{{ $id }}.getMuted();
|
||||
wavesurfer_{{ $id }}.setMuted(isMuted);
|
||||
if(isMuted) {
|
||||
$('#{{ $id }} .btn-toggle-mute').html('<span class="fa fa-volume-xmark"></span>');
|
||||
$('#{{ $id }} .volume-slider').attr('disabled', 'disabled');
|
||||
} else {
|
||||
$('#{{ $id }} .btn-toggle-mute').html('<span class="fa fa-volume-high"></span>');
|
||||
$('#{{ $id }} .volume-slider').removeAttr('disabled');
|
||||
}
|
||||
});
|
||||
// Hover effect
|
||||
{
|
||||
const hover = document.querySelector('#{{ $id }} .hover')
|
||||
const waveform = document.querySelector('#{{ $id }} .waveform')
|
||||
waveform.addEventListener('pointermove', (e) => (hover.style.width = `${e.offsetX}px`))
|
||||
}
|
||||
|
||||
// Current time & duration
|
||||
{
|
||||
const formatTime = (seconds) => {
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
const secondsRemainder = Math.round(seconds) % 60
|
||||
const paddedSeconds = `0${secondsRemainder}`.slice(-2)
|
||||
return `${minutes}:${paddedSeconds}`
|
||||
}
|
||||
|
||||
const timeEl = document.querySelector('#{{ $id }} .time')
|
||||
const durationEl = document.querySelector('#{{ $id }} .duration')
|
||||
wavesurfer_{{ $id }}.on('decode', (duration) => (durationEl.textContent = formatTime(duration)))
|
||||
wavesurfer_{{ $id }}.on('timeupdate', (currentTime) => (timeEl.textContent = formatTime(currentTime)))
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#{{ $id }} .waveform {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#{{ $id }} .hover {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
height: 100%;
|
||||
width: 0;
|
||||
mix-blend-mode: overlay;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
#{{ $id }} .waveform:hover .hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#{{ $id }} .time,
|
||||
#{{ $id }} .duration {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
top: 50%;
|
||||
margin-top: -1px;
|
||||
transform: translateY(-50%);
|
||||
font-size: 11px;
|
||||
background: rgba(0, 0, 0, 0.75);
|
||||
padding: 2px;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
#{{ $id }} .time {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#{{ $id }} .duration {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#{{ $id }} .audio-controls {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#{{ $id }} .audio-controls .btn {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
@media(max-width:720px) {
|
||||
#{{ $id }} .audio-controls .btn label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#{{ $id }} .audio-controls .btn.btn-play {
|
||||
flex: 50% 1 0;
|
||||
}
|
||||
|
||||
#{{ $id }} .volume-controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#{{ $id }} .volume-controls .volume-slider
|
||||
{
|
||||
flex: 100% 1 1;
|
||||
}
|
||||
|
||||
#{{ $id }} .audio-controls .btn,
|
||||
#{{ $id }} .volume-controls .btn-toggle-mute {
|
||||
flex: 100px 1 1;
|
||||
padding: 10px 0px 10px 0px;
|
||||
background: #5ba8f4;
|
||||
border-radius: 5px;
|
||||
border-color: solid 1px #0f259d;
|
||||
color: white;
|
||||
font-family: Nunito, serif;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user