Private
Public Access
1
0

Merge tag 'v10.79' into develop

mini video view
This commit is contained in:
Sander Roosendaal
2020-01-03 17:21:38 +01:00
5 changed files with 807 additions and 1 deletions

4
app.py
View File

@@ -1,8 +1,10 @@
#!/usr/bin/env python
#!/srv/bin/venv python3.6
import os
import sys
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rowsandall_app.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
#execute_from_command_line(sys.argv)

View File

@@ -40,6 +40,10 @@
$(this).removeAttr('disabled');
});
});
document.getElementById("smallscreen").style.display = "none";
if ($(window).width() <= 950) {
$("#smallscreen").show()
}
});
</script>
<script>
@@ -104,6 +108,12 @@ function copyText() {
{% language 'en' %}
<h1>Video Analysis for {{ workout.name }}</h1>
<ul class="main-content">
<li class="grid_4" id="smallscreen">
<p>Your screen is too small to show the full functionality. Click
<a href="/rowers/video/{{ analysis.id|encode }}/m">here</a>
to get to a version that is better suited for small screens.
</p>
</li>
{% if user.is_authenticated and user == workout.user.user and not locked %}
<li class="grid_2">
<p>Paste link to you tube video below</p>

View File

@@ -0,0 +1,682 @@
{% extends "newbase.html" %}
{% load staticfiles %}
{% load rowerfilters %}
{% load i18n %}
{% load leaflet_tags %}
{% block title %}Workout Video{% endblock %}
{% block og_title %}{{ analysis.name }}{% endblock %}
{% block description %}Rowing Video Analysis:{{ analysis.name }}{% endblock %}
{% block og_description %}Rowing Video Analysis:{{ analysis.name }}{% endblock %}
{% block og_image %}
{% if analysis %}
<meta property="og:image" content="https://img.youtube.com/vi/{{ analysis.video_id }}/hqdefault.jpg" />
<meta property="og:image:secure_url" content="https://img.youtube.com/vi/{{ analysis.video_id }}/hqdefault.jpg" />
{% else %}
<meta property="og:image" content="http://rowsandall.com/static/img/logo_r.png" />
<meta property="og:image:secure_url" content="https://rowsandall.com/static/img/logo_r.png" />
{% endif %}
{% endblock %}
{% if analysis %}
{% block image_src %}
<link rel="image_src" href="https://img.youtube.com/vi/{{ analysis.video_id }}/hqdefault.jpg" />
{% endblock %}
{% endif %}
{% block meta %}
{% leaflet_js %}
{% leaflet_css %}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript" src="{% static 'js/videogauges.js' %}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function() {
$('form').submit(function(e) {
$(':disabled').each(function(e) {
$(this).removeAttr('disabled');
});
});
});
</script>
<script>
function copyText() {
var tempInput = document.createElement("input");
tempInput.style = "position: absolute; left: -1000px; top: -1000px";
tempInput.value = "{{ siteurl }}/rowers/video/{{ analysis.id|encode }}/";
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
alert("Copied to clipboard: " + tempInput.value);
document.body.removeChild(tempInput);
}
</script>
{% endblock %}
{% block main %}
<style>
.slidecontainer {
width: 100%; /* Width of the outside container */
}
.bold { font-weight: bold; }
/* The slider itself */
.slider {
-webkit-appearance: none; /* Override default CSS styles */
appearance: none;
width: 100%; /* Full-width */
height: 25px; /* Specified height */
background: #d3d3d3; /* Grey background */
outline: none; /* Remove outline */
opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
-webkit-transition: .2s; /* 0.2 seconds transition on hover */
transition: opacity .2s;
}
/* Mouse-over effects */
.slider:hover {
opacity: 1; /* Fully shown on mouse-over */
}
/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
.slider::-webkit-slider-thumb {
-webkit-appearance: none; /* Override default look */
appearance: none;
width: 25px; /* Set a specific slider handle width */
height: 25px; /* Slider handle height */
background: #4CAF50; /* Green background */
cursor: pointer; /* Cursor on hover */
}
.slider::-moz-range-thumb {
width: 25px; /* Set a specific slider handle width */
height: 25px; /* Slider handle height */
background: #4CAF50; /* Green background */
cursor: pointer; /* Cursor on hover */
}
</style>
{% language 'en' %}
<h1>Video Analysis for {{ workout.name }}</h1>
<ul class="main-content">
<li class="grid_4">
<p>Playing the video will advance the data in synchronization. Use the regular
YouTube controls to move around in the video and play it.</p>
</li>
<li class="grid_4">
<span class="fb-share-button" style="height:20px; vertical-align: top;"
data-href="{{ siteurl }}/rowers/video/{{ analysis.id|encode }}"
data-layout="button" data-size="small" data-mobile-iframe="false">
<a class="fb-xfbml-parse-ignore" target="_blank"
href="https://www.facebook.com/sharer/sharer.php?u=https://rowsandall.com/rowers/video/{{ analysis.id|encode }}/">
Share</a>
</span>
<span>
<a class="twitter-share-button"
href="https://twitter.com/intent/tweet"
data-url="{{ siteurl }}/rowers/video/{{ analysis.id|encode }}/"
data-text="@rowsandall #rowingdata">Tweet</a>
</span>
<span>
<button title="Copy Shareable Link" onclick="copyText()"
style="color:#1c75bc;background:none;border:0;"><i class="fas fa-copy"></i></button>
</span>
</li>
</ul>
<ul class="main-content">
<li class="grid_3">
<div id="theplot" class="flexplot mapdiv">
{{ mapdiv | safe}}
</div>
<div class="slidecontainer">
<input type="range" min="0" max="{{ maxtime }}" value="{{ analysis.delay }}"
id="myRange">
</div>
<div id="dataplay"></div>
<!-- <div id="datastop"></div> -->
</li>
<li class="grid_4">
<div id="player"></div>
<script>
// 1. Code for the map
{{ mapscript | safe }}
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
var playing = false;
var dataplaying = false;
var videotime = 0;
var data = JSON.parse('{{ data|safe }}');
{% for id, metric in metrics.items %}
var {{ id }}_values = data["{{ id }}"];
// console.log("{{ id }}_values",{{ id }}_values);
{% endfor %}
// var boatspeed = data["boatspeed"];
var latitude = data["latitude"];
var longitude = data["longitude"];
// var spm = data["spm"];
// var ctch = data["catch"];
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '315',
width: '560',
modestbranding: '1',
videoId: '{{ video_id }}',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
// event.target.playVideo();
}
function updateTime() {
var oldTime = videotime;
var slider = document.getElementById("myRange");
var lock = document.getElementById("lock");
if(player && player.getCurrentTime) {
videotime = player.getCurrentTime();
var delay = document.getElementById("id_delay").value;
if (lock.checked) {
sliderpos = Math.round(videotime) + Math.round(delay);
slider.value = sliderpos;
}
// gauge.set(catch_now);
}
if(videotime !== oldTime) {
onProgress(videotime);
}
}
timeupdater = setInterval(updateTime, 1000);
// when the time changes, this will be called.
function onProgress(currentTime) {
var slider = document.getElementById("myRange");
var lock = document.getElementById("lock");
videotime = player.getCurrentTime();
var delay = document.getElementById("id_delay").value;
var output = document.getElementById("id_delay");
datatime = slider.value;
if (lock.checked) {
if (!dataplaying) { // set data values
sliderpos = Math.round(videotime) + Math.round(delay);
slider.value = sliderpos;
// Setting Data
// velo = boatspeed[Math.round(datatime)];
lat = latitude[Math.round(datatime)];
lon = longitude[Math.round(datatime)];
// strokerate = spm[Math.round(datatime)];
// catchangle = ctch[Math.round(datatime)];
{% for id, metric in metrics.items %}
{{ id }}_now = {{ id }}_values[Math.round(datatime)];
// console.log(datatime,{{ id }},{{ id }}_now, "{{ metric.name }}")
{% endfor %}
{% for group in metricsgroups %}
try {
set_{{ group }}();
} catch (e) {
console.log(e);
}
{% endfor %}
try {
var newLatLng = new L.LatLng(lat, lon);
// console.log(newLatLng);
marker.setLatLng(newLatLng);
} catch (e) {
}
}
} else {
if (!dataplaying) {
output.value = Math.round(datatime)-Math.round(videotime);
}
}
}
function stopVideo() {
player.pauseVideo();
playing = false;
}
// call this function when player state changes
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && lock.checked) {
var dataplay = document.getElementById("dataplay").childNodes[0];
dataplay.value = String.fromCharCode(10074,10074);
} else if (lock.checked) {
var dataplay = document.getElementById("dataplay").childNodes[0];
dataplay.value = String.fromCharCode(9658);
}
}
</script>
</li>
<li class="grid_4">
<input type="hidden" name="lock" id="lock" value="Lock">
</li>
</ul>
<p>&nbsp;</p>
<form enctype="multipart/form-data" action="" method="post">
<ul class="main-content">
<li class="grid_4">
<input type="hidden" id="id_delay" value="{{ analysis.delay }}">
</li>
<li class="grid_4" >
<ul class="main-content">
{% if 'basic' in metricsgroups %}
<li class="grid_1">
<div id="basic_spm"></div>
</li>
<li class="grid_1">
<div id="basic_boatspeed"></div>
</li>
{% endif %}
{% if 'forcepower' in metricsgroups %}
<li class="grid_1">
<div id="forcepower_power"></div>
</li>
{% endif %}
{% if 'athlete' in metricsgroups %}
<li class="grid_1">
<div id="athlete_hr"></div>
</li>
{% endif %}
{% if 'stroke' in metricsgroups %}
{% if workout.workouttype == 'water' %}
<li class="grid_1" style="height:500px">
<div style="width:100%;height:70%;" id="stroke_angles"></div>
</li>
{% endif %}
{% endif %}
</ul>
</li>
</ul>
</form>
<p>&nbsp;</p>
<script>
$(document).ready( function() {
$(window).load(function() {
// initialize data fields
console.log('initializing first value of data');
{% for id, metric in metrics.items %}
{{ id }}_now = {{ id }}_values[0];
{% endfor %}
var slider = document.getElementById("myRange");
// gauge settings
{% if workout.workouttype != 'water' %}
speedoptions.max = 7;
speedoptions.redTo = 7;
speedoptions.majorTicks = ['0','1','2','3','4','5','6','7'];
{% endif %}
{% if 'basic' in metricsgroups %}
spm_now = spm_values[0];
boatspeed_now = boatspeed_values[0];
set_basic();
{% endif %}
{% if 'forcepower' in metricsgroups %}
poweroptions.max = {{ workout.user.pw_an|add:100|round100 }};
poweroptions.greenFrom = {{ workout.user.pw_ut2 }};
poweroptions.greenTo = {{ workout.user.pw_at }};
poweroptions.yellowFrom = {{ workout.user.pw_at }};
poweroptions.yellowTo = {{ workout.user.pw_an }};
poweroptions.redFrom = {{ workout.user.pw_an }};
poweroptions.redTo = {{ workout.user.pw_an|add:100|round100 }};
poweroptions.majorTicks = {{ workout.user.pw_an|add:100|round100|majorticks }};
{% if workout.workouttype == 'water' %}
poweroptions.max = {{ workout.user.pw_an|waterpower:workout.user|add:100|round100 }}
poweroptions.greenFrom = {{ workout.user.pw_ut2|waterpower:workout.user }};
poweroptions.greenTo = {{ workout.user.pw_at|waterpower:workout.user }};
poweroptions.yellowFrom = {{ workout.user.pw_at|waterpower:workout.user }};
poweroptions.yellowTo = {{ workout.user.pw_an|waterpower:workout.user }};
poweroptions.redFrom = {{ workout.user.pw_an|waterpower:workout.user }};
poweroptions.redTo = {{ workout.user.pw_an|waterpower:workout.user|add:100|round100 }};
poweroptions.majorTicks = {{ workout.user.pw_an|waterpower:workout.user|add:100|round100|majorticks }};
{% endif %}
power_now = power_values[0];
set_forcepower();
{% endif %}
{% if 'athlete' in metricsgroups %}
hroptions.max = {{ workout.user.max|round20 }}
hroptions.greenFrom = {{ workout.user.ut2 }}
hroptions.greenTo = {{ workout.user.at }}
hroptions.yellowFrom = {{ workout.user.at }}
hroptions.yellowTo = {{ workout.user.an }}
hroptions.redFrom = {{ workout.user.an }}
hroptions.redTo = {{ workout.user.max }}
hroptions.majorTicks = {{ workout.user.max|round20|hrmajorticks:workout.user.rest }}
hr_now = hr_values[0];
set_athlete();
{% endif %}
{% if 'stroke' in metricsgroups %}
{% if workout.workouttype == 'water' %}
anglesoptions.PieStartAngle = 90+catch_now;
set_stroke();
{% endif %}
{% endif %}
// cookie reader
function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
// lock
var lock = document.getElementById("lock");
var output = document.getElementById("id_delay");
var cookie = readCookie("lock{{ workout.id }}");
var delay = output.value;
if (cookie=="true") {
lock.checked = true;
output.disabled = true;
}
// lock.onchange nog doen
{% if locked %}
lock.checked = true;
output.disabled = true;
{% endif %}
// slider
var slider = document.getElementById("myRange");
{% if user.is_authenticated and user == workout.user.user %}
document.getElementById("myRange").style.display = "block";
{% else %}
document.getElementById("myRange").style.display = "none";
{% endif %}
var output = document.getElementById("id_delay");
// Update the current slider value (each time you drag the slider handle)
slider.oninput = function() {
if (!lock.checked) {
try {
delay = Math.round(slider.value)-Math.round(player.getCurrentTime());
output.value = Math.round(slider.value)-Math.round(player.getCurrentTime()); // Display the default slider value
}
catch(err) {
output.value = Math.round(slider.value);
delay = Math.round(slider.value);
}
}
clearInterval(timeupdater);
var datatime = this.value
var videotime = Math.round(player.getCurrentTime());
if (lock.checked) {
if (this.value-output.value > 0) {
player.seekTo(this.value-output.value);
videotime = this.value-output.value;
} else {
if (playing && !dataplaying) {
player.seekTo(0);
player.playVideo();
}
else if (!playing && !dataplaying) {
player.seekTo(0);
player.pauseVideo();
playing = false;
}
}
} else {
// console.log('changing, not checked');
output.value = this.value-Math.round(player.getCurrentTime());
}
// Setting Data
// velo = boatspeed[Math.round(datatime)];
lat = latitude[Math.round(datatime)];
lon = longitude[Math.round(datatime)];
// strokerate = spm[Math.round(datatime)];
// catchangle = ctch[Math.round(datatime)];
{% for id, metric in metrics.items %}
{{ id }}_now = {{ id }}_values[Math.round(datatime)];
// console.log(datatime,{{ id }}_now, "{{ metric.name }}")
{% endfor %}
{% for group in metricsgroups %}
try {
set_{{ group }}();
} catch (e) {
}
{% endfor %}
try {
var newLatLng = new L.LatLng(lat, lon);
// console.log(newLatLng);
marker.setLatLng(newLatLng);
} catch (e) {
}
timeupdater = setInterval(updateTime, 1000);
}
output.oninput = function() {
slider.value = this.value+Math.round(player.getCurrentTime());
}
// Update the current slider value (each time the slider is changed)
slider.onchange = function() {
clearInterval(timeupdater)
if (lock.checked) {
if (this.value-output.value > 0) {
player.seekTo(this.value-output.value);
if (playing) {
player.playVideo();
} else {
player.pauseVideo();
}
} else {
if (playing) {
player.seekTo(0);
player.playVideo();
}
else {
player.seekTo(0);
player.pauseVideo();
playing = false;
}
}
} else {
output.value = this.value-Math.round(player.getCurrentTime());
}
var datatime = this.value
var videotime = Math.round(player.getCurrentTime());
//
// Setting Data
// velo = boatspeed[Math.round(datatime)];
lat = latitude[Math.round(datatime)];
lon = longitude[Math.round(datatime)];
// strokerate = spm[Math.round(datatime)];
// catchangle = ctch[Math.round(datatime)];
{% for id, metric in metrics.items %}
{{ id }}_now = {{ id }}_values[Math.round(datatime)];
// console.log(datatime,{{ id }}_now, "{{ metric.name }}")
{% endfor %}
{% for group in metricsgroups %}
try {
set_{{ group }}();
} catch (e) {
console.log(e);
}
{% endfor %}
try {
var newLatLng = new L.LatLng(lat, lon);
// console.log(newLatLng);
marker.setLatLng(newLatLng);
} catch (e) {
console.log('error')
}
console.log('changed all')
timeupdater = setInterval(updateTime, 1000);
}
output.oninput = function() {
slider.value = this.value+Math.round(player.getCurrentTime());
}
// lock delay form field if checkbox checked
lock.oninput = function() {
if (this.checked) {
output.disabled = true;
createCookie("lock{{ workout.id}}","true",0);
} else {
output.disabled = false;
createCookie("lock{{ workout.id }}","false",0);
}
}
// Slider start stop
// moet de buttons pas hieronder definieren en dan in de html
// pluggen
var timer;
function clock() {
timer = setInterval(myClock, 1000);
var c = parseInt(slider.value,10);
console.log('starting clock');
function myClock() {
c = c+1;
slider.value = c;
// update data fields
lat = latitude[Math.round(c)];
lon = longitude[Math.round(c)];
{% for id, metric in metrics.items %}
{{ id }}_now = {{ id }}_values[Math.round(c)];
// console.log(datatime,{{ id }}_now, "{{ metric.name }}")
{% endfor %}
{% for group in metricsgroups %}
try {
set_{{ group }}();
} catch (e) {}
{% endfor %}
try {
var newLatLng = new L.LatLng(lat, lon);
// console.log(newLatLng);
marker.setLatLng(newLatLng);
} catch (e) {
}
if (lock.checked) {
player.seekTo(c+parseInt(output.value));
} else {
delay = Math.round(slider.value)-Math.round(player.getCurrentTime());
output.value = Math.round(slider.value)-Math.round(player.getCurrentTime());
}
if (c == latitude.length) {
clearInterval(timer);
c = 0;
}
}
}
// onderstaande alleen als lock.checked
var dataplay = document.createElement("input");
dataplay.type = "button";
dataplay.value = String.fromCharCode(9658);
document.getElementById("dataplay").appendChild(dataplay);
// var datastop = document.createElement("input");
// datastop.type = "button";
// datastop.value = "Stop";
// document.getElementById("datastop").appendChild(datastop)
dataplay.onclick = function() {
if (lock.checked) {
dataplaying = false;
if (playing == false) {
player.playVideo();
dataplay.value = String.fromCharCode(10074,10074);
playing = true;
} else {
player.pauseVideo();
dataplay.value = String.fromCharCode(9658);
playing = false;
}
} else {
if (!dataplaying) {
clock();
dataplay.value = String.fromCharCode(10074,10074);
dataplaying = true;
if (lock.checked) {
playing = true;
}
} else {
clearInterval(timer);
dataplay.value = String.fromCharCode(9658);
dataplaying = false;
}
}
}
});
});
</script>
{% endlanguage %}
{% endblock %}
{% block sidebar %}
{% include 'menu_workout.html' %}
{% endblock %}

View File

@@ -346,6 +346,8 @@ urlpatterns = [
re_path(r'^workout/(?P<id>\b[0-9A-Fa-f]+\b)/video/$',views.workout_video_create_view,
name='workout_video_create_view'),
re_path(r'^video/(?P<pk>\d+)/delete/$',views.VideoDelete.as_view(),name='video_delete'),
re_path(r'^video/(?P<id>\w.+)/m/$',views.workout_video_view_mini,
name='workout_video_view_mini'),
re_path(r'^video/(?P<id>\w.+)/$',views.workout_video_view,
name='workout_video_view'),
re_path(r'^videos/',views.list_videos,name='list_videos'),

View File

@@ -48,6 +48,116 @@ def get_video_id(url):
else:
raise ValueError
# Show a video compared with data
def workout_video_view_mini(request,id=''):
try:
id = encoder.decode_hex(id)
analysis = VideoAnalysis.objects.get(id=id)
except VideoAnalysis.DoesNotExist:
raise Http404("Video Analysis does not exist")
w = analysis.workout
delay = analysis.delay
if w.workouttype in mytypes.otwtypes:
mode = 'water'
else:
mode = 'erg'
if request.user.is_authenticated:
mayedit = checkworkoutuser(request.user,w) and isprorower(request.user.rower)
rower = request.user.rower
else:
mayedit = False
rower = None
# get video ID and offset
if mayedit and request.method == 'POST':
form = VideoAnalysisCreateForm(request.POST)
metricsform = VideoAnalysisMetricsForm(request.POST,mode=mode)
if form.is_valid() and metricsform.is_valid():
video_id = form.cleaned_data['url']
try:
video_id = get_video_id(form.cleaned_data['url'])
except (TypeError,ValueError):
pass
delay = form.cleaned_data['delay']
metricsgroups = metricsform.cleaned_data['groups']
if 'save_button' in request.POST:
analysis.name = form.cleaned_data['name']
analysis.video_id = video_id
analysis.delay = delay
analysis.metricsgroups = metricsgroups
analysis.save()
else:
video_id = id
delay = 0
elif mayedit:
form = VideoAnalysisCreateForm(
initial = {
'name':analysis.name,
'delay': analysis.delay,
'url': analysis.video_id,
}
)
metricsform = VideoAnalysisMetricsForm(initial={'groups':analysis.metricsgroups},
mode=mode)
metricsgroups = analysis.metricsgroups
video_id = analysis.video_id
else:
form = None
metricsform = None
metricsgroups = analysis.metricsgroups
data, metrics, maxtime = dataprep.get_video_data(w,groups=metricsgroups,mode=mode)
hascoordinates = pd.Series(data['latitude']).std() > 0
# create map
if hascoordinates:
mapscript, mapdiv = leaflet_chart_video(data['latitude'],data['longitude'],
w.name)
else:
mapscript, mapdiv = interactive_chart_video(data)
data['longitude'] = data['spm']
data['latitude'] = list(range(len(data['spm'])))
breadcrumbs = [
{
'url':'/rowers/list-workouts/',
'name':'Workouts'
},
{
'url':get_workout_default_page(request,encoder.encode_hex(w.id)),
'name': w.name
},
{
'url':reverse('workout_video_view',kwargs={'id':encoder.encode_hex(analysis.id)}),
'name': 'Video Analysis'
}
]
return render(request,
'embedded_video_mini.html',
{
'workout':w,
'rower':rower,
'data': json.dumps(data,default=default),
'mapscript': mapscript,
'mapdiv': mapdiv,
'video_id': analysis.video_id,
'form':form,
'breadcrumbs':breadcrumbs,
'analysis':analysis,
'maxtime':maxtime,
'metrics':metrics,
'locked': True,
'metricsform':metricsform,
'metricsgroups': metricsgroups,
'siteurl': settings.SITE_URL,
})
# Show a video compared with data
def workout_video_view(request,id=''):