added audio, video previews, fixed image previews

This commit is contained in:
Alexander Karpov 2023-04-12 13:14:34 +03:00
parent 8a995a8ca5
commit e7d78d59ec
10 changed files with 200 additions and 15 deletions

View File

@ -1,3 +1,20 @@
from . import image, video
from . import audio, image, video
previews = {"video": {"mp4": video.mp4.view}, "image": {"jpeg": image.jpeg.view}}
previews = {
"audio": {
"aac": audio.basic.view,
"mpeg": audio.basic.view,
"ogg": audio.basic.view,
"opus": audio.basic.view,
"wav": audio.basic.view,
"webm": audio.basic.view,
},
"video": {"mp4": video.mp4.view},
"image": {
"jpeg": image.basic.view,
"png": image.basic.view,
"avif": image.basic.view,
},
}
extensions = {"mp4": video.mp4.view, "mp3": audio.basic.view, "avif": image.basic.view}

View File

@ -0,0 +1 @@
from . import basic # noqa

View File

@ -0,0 +1,61 @@
from akarpov.files.models import File
def view(file: File) -> (str, str):
static = """
"""
content = (
"""
<div id="waveform">
</div>
<div id="wave-timeline"> </div>
<div class="controls mt-4 d-flex align-items-center justify-content-center text-center">
<button class="btn btn-primary" data-action="play">
<i class="glyphicon glyphicon-play"></i>
Play
/
<i class="glyphicon glyphicon-pause"></i>
Pause
</button>
</div>
<script src="https://unpkg.com/wavesurfer.js@6.6.3/dist/wavesurfer.js"></script>
<script src="https://unpkg.com/wavesurfer.js@6.6.3/dist/plugin/wavesurfer.timeline.min.js"></script>
<script src="https://unpkg.com/wavesurfer.js@6.6.3/dist/plugin/wavesurfer.regions.min.js"></script>
<script>
window.onload = function() {
wavesurfer = WaveSurfer.create({
container: document.querySelector('#waveform'),
waveColor: '#D9DCFF',
progressColor: '#4353FF',
cursorColor: '#4353FF',
barWidth: 3,
barRadius: 3,
cursorWidth: 1,
height: 200,
barGap: 3,
plugins: [
WaveSurfer.regions.create({}),
WaveSurfer.timeline.create({
container: "#wave-timeline"
})
]
});
wavesurfer.on('error', function(e) {
console.warn(e);
});
"""
+ f"""
wavesurfer.load('{file.file.url}');
"""
+ """
document
.querySelector('[data-action="play"]')
.addEventListener('click', wavesurfer.playPause.bind(wavesurfer));
}
</script>
"""
)
return static, content

View File

@ -0,0 +1,102 @@
from akarpov.files.models import File
def view(file: File) -> (str, str):
static = """
<style>
#canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
"""
content = (
"""
<div id="container">
<canvas id="canvas"></canvas>
<audio id="audio"></audio>
</div>
"""
+ """
<script>
const container = document.getElementById("container");
container.addEventListener("click", function () {
let audio1 = new Audio();
"""
+ f"""
audio1.src = "{file.file.url}";
"""
+ """
audio1.crossOrigin = "anonymous";
const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); // for safari browser
const container = document.getElementById("container");
const canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext("2d");
let audioSource = null;
let analyser = null;
audio1.play();
audioSource = audioCtx.createMediaElementSource(audio1);
analyser = audioCtx.createAnalyser();
audioSource.connect(analyser);
analyser.connect(audioCtx.destination);
analyser.fftSize = 128;
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
const barWidth = canvas.width / 2 / bufferLength;
let x = 0;
function animate() {
x = 0;
ctx.clearRect(0, 0, canvas.width, canvas.height); // clears the canvas
analyser.getByteFrequencyData(dataArray);
drawVisualizer({ bufferLength, dataArray, barWidth });
requestAnimationFrame(animate); // calls the animate function again. This method is built in
}
const drawVisualizer = ({ bufferLength, dataArray, barWidth }) => {
let barHeight;
for (let i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
const red = (i * barHeight) / 10;
const green = i * 4;
const blue = barHeight / 4 - 12;
ctx.fillStyle = `rgb(${red}, ${green}, ${blue})`;
ctx.fillRect(
canvas.width / 2 - x, // this will start the bars at the center of the canvas and move from right to left
canvas.height - barHeight,
barWidth,
barHeight
);
x += barWidth; // increases the x value by the width of the bar
}
for (let i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
const red = (i * barHeight) / 10;
const green = i * 4;
const blue = barHeight / 4 - 12;
ctx.fillStyle = `rgb(${red}, ${green}, ${blue})`;
ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
x += barWidth; // increases the x value by the width of the bar
}
};
animate();
});
</script>
"""
)
return static, content

View File

@ -1 +1 @@
from . import jpeg # noqa
from . import basic # noqa

View File

@ -10,6 +10,8 @@ def view(file: File) -> (str, str):
<div>
<img id="image" class="img-fluid" src="{file.file.url}" alt="Picture">
</div>
<div id="images">
</div
<script src="/static/js/jquery.js"></script>
"""
+ """
@ -23,10 +25,7 @@ def view(file: File) -> (str, str):
}
});
// Get the Viewer.js instance after initialized
var viewer = $image.data('viewer');
// View a list of images
$('#images').viewer();
</script>
"""

View File

@ -9,7 +9,7 @@ def view(file: File) -> (str, str):
content = f"""
<video id="my_video_1" class="video-js vjs-default-skin" height="500px"
controls poster='{file.preview.url}'
controls poster='{file.preview.url if file.preview else ''}'
data-setup='{data}'>
<source src="{file.file.url}" type='video/mp4' />
</video>

View File

@ -11,7 +11,7 @@
ChunkedUploadView,
)
from akarpov.files.models import File, Folder
from akarpov.files.previews import previews
from akarpov.files.previews import extensions, previews
class TopFolderView(LoginRequiredMixin, ListView):
@ -41,6 +41,11 @@ def get_context_data(self, **kwargs):
static = ""
content = ""
if self.object.file_type:
if self.object.file_type == "application/octet-stream":
extension = self.object.file.path.split(".")[-1]
if extension in extensions:
static, content = extensions[extension](self.object)
else:
t1, t2 = self.object.file_type.split("/")
if t1 in previews:
if t2 in previews[t1]:

View File

@ -8,7 +8,7 @@
{% block content %}
<div class="row m-2">
<div class="col-auto">
<div class="col-md-4 col-sm-6">
<h1 class="fs-1">{{ file.name }}</h1>
{% if not has_perm %}
<p>Uploaded by: <a href="{% url 'users:detail' file.user.username %}">
@ -24,7 +24,7 @@
<p>{{ file.description }}</p>
{% endif %}
</div>
<div class="col-auto">
<div class="col-md-8 col-sm-10">
{% autoescape off %}
{{ preview_content }}
{% endautoescape %}

View File

@ -7,4 +7,4 @@ dpkg -i draw.io-amd64-13.0.3.deb
rm draw.io-amd64-13.0.3.deb
apt-get purge -y --auto-remove -o APT:AutoRemove:RecommendsImportant=false && \
rm -rf /var/lib/apt/lists/*
preview --check-dependencies``
preview --check-dependencies