Skip to content

Commit f37d36b

Browse files
committed
Initial version
0 parents  commit f37d36b

11 files changed

+294
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__pycache__
2+
.DS_Store

.vscode/settings.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"python.pythonPath": "/usr/local/bin/python3",
3+
"python.linting.pylintEnabled": false,
4+
"python.linting.pep8Enabled": true,
5+
"python.linting.enabled": true
6+
}

README.md

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Python Video to HTML Canvas Demo
2+
3+
This script can create a Javascript object with video information from a video file.
4+
5+
The javascript object can be played in **HTML Canvas** as a sequence of frames with pixel data.
6+
7+
8+
## Python packages
9+
10+
* `opencv-python`: OpenCV, Open Source Computer Vision Library. BSD license and hence it’s free for both academic and commercial use.
11+
12+
## Usage
13+
14+
### Python code example
15+
16+
```python
17+
import sys
18+
from video_convert import video_to_js
19+
20+
filein = "example/multi.mov"
21+
fileout = "html/video.js"
22+
video_to_js(filein, 200, 200, 1, 15, fileout)
23+
```
24+
25+
### Video example (included)
26+
27+
This example will generate the file `html/video.js`:
28+
29+
`python example.py example/multi.mov`
30+
31+
32+
33+
### Javascript Video usage
34+
35+
36+
Use this code snippet to embed your video in Canvas
37+
38+
```html
39+
<canvas id=canvas></canvas>
40+
<script src="video.js" ></script>
41+
<script src="player.js" ></script>
42+
<script >
43+
document.body.onload=function(){
44+
var player = new VideoPlayer("canvas", video)
45+
player.startVideo()
46+
}
47+
</script>
48+
```
49+
50+
Where `video.js` is the video file generated by the script, and `player.js` is the Video player component to play the video vile format.
51+

example.py

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import sys
2+
from video_convert import video_to_js
3+
4+
try:
5+
filein = sys.argv[1]
6+
fileout = "html/video.js"
7+
video_to_js(filein, 120, 150, 1, 15, fileout)
8+
except:
9+
print("Usage: %s video_file" % sys.argv[0])

example/multi.mov

124 KB
Binary file not shown.

html/index.html

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<title>Python Video to HTML Canvas Demo</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1">
8+
<style>
9+
button{
10+
border-radius:7px;
11+
border: 1px solid #eee;
12+
padding:4px;
13+
margin: 3px;
14+
}
15+
</style>
16+
</head>
17+
<body>
18+
<h2>Python Video to Javascript Demo</h2>
19+
<button onclick="player.startVideo()">Play</button>
20+
<button onclick="player.stopVideo()">Stop</button>
21+
<br>
22+
<canvas id=canvas></canvas>
23+
<br>
24+
<button onclick="video.freq=base_freq*4">Slower</button>
25+
<button onclick="video.freq=base_freq*2">Slow</button>
26+
<button onclick="video.freq=base_freq">Nomal</button>
27+
<button onclick="video.freq=base_freq/2">Fast</button>
28+
29+
<script src="video.js" ></script>
30+
<script src="player.js" ></script>
31+
<script >
32+
document.body.onload=function(){
33+
base_freq = video.freq
34+
player = new VideoPlayer("canvas", video)
35+
player.startVideo()
36+
}
37+
</script>
38+
<br><small id="info"></small>

html/player.js

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
2+
function VideoPlayer(canvasId, video){
3+
4+
var canvas = document.getElementById(canvasId);
5+
var ctx = canvas.getContext('2d');
6+
var lastFrame = []
7+
var lastVideo = 0
8+
9+
canvas.setAttribute("width",video.width)
10+
canvas.setAttribute("height",video.height)
11+
12+
13+
this.playVideo=function(video,freq){
14+
fps=freq
15+
if (!fps){
16+
fps=video.freq
17+
}
18+
console.log("Playing at "+fps+"fps")
19+
for(var i=0; i<video.data.length-1; i++){
20+
lastFrame[i]=setTimeout(this.playFrame.bind(this),fps*i,i,video.data[i],video)
21+
}
22+
lastVideo=setTimeout(this.playVideo.bind(this),fps*video.data.length-2,video,freq)
23+
}
24+
25+
this.writeText=function(ctx,text, px){
26+
ctx.font = '10px Arial';
27+
ctx.fillStyle='white';
28+
ctx.fillText(text, px+5, 10);
29+
ctx.fillText(text, px+7, 12);
30+
ctx.fillStyle='black';
31+
ctx.fillText(text, px+6, 11);
32+
}
33+
34+
this.playFrame=function(i,frame,video){
35+
ctx.fillRect(0,0,video.width,video.height)
36+
var d = ctx.createImageData(video.frame_width, video.frame_height);
37+
var f=0;
38+
for(var px=0;px<frame.length; px++){
39+
var value=parseInt(frame[px],10)
40+
d.data[f]=value*26; f++;
41+
if((px+1)%3==0){
42+
d.data[f]=255;
43+
f++;
44+
}
45+
}
46+
var padx=(video.width-video.frame_width)/2
47+
ctx.putImageData(d, padx, 0);
48+
this.writeText(ctx,"Frame "+i,padx)
49+
}
50+
51+
this.stopVideo=function(){
52+
this.pauseVideo();
53+
window.clearTimeout(lastVideo)
54+
lastVideo=0
55+
}
56+
57+
this.pauseVideo=function(){
58+
for(var f=0; f<lastFrame.length; f++){
59+
window.clearTimeout(lastFrame[f])
60+
}
61+
lastFrame=[]
62+
}
63+
64+
this.startVideo=function(){
65+
if (lastFrame.length){
66+
return
67+
}
68+
this.playVideo(video)
69+
}
70+
71+
}

html/video.js

+26
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
opencv-python

video_convert.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import sys
2+
from video_utils import get_video, get_video_props, get_frame, pixel_to_rgb
3+
4+
5+
def video_to_js(infile, cwidth, cheight, frame_start, frame_end, outfile=None):
6+
opacity = 255
7+
comp = 26
8+
cap = get_video(infile)
9+
if outfile is None:
10+
writer = sys.stdout
11+
else:
12+
writer = open(outfile, "w")
13+
print("Writing to %s ..." % outfile)
14+
width, height, length, real_fps = get_video_props(cap)
15+
real_freq = int(1000/real_fps)
16+
17+
writer.write("video ={\n")
18+
writer.write('"width":%s,\n' % cwidth)
19+
writer.write('"height":%s,\n' % cheight)
20+
writer.write('"fps":%s,\n' % real_fps)
21+
writer.write('"freq":%s,\n' % real_freq)
22+
writer.write('"data":[\n')
23+
fn = 0
24+
i = 0
25+
fwidth = 0
26+
fheight = 0
27+
for rframe in get_frame(cap, cwidth, cheight):
28+
fn += 1
29+
if fn < frame_start:
30+
continue
31+
if fn > frame_end:
32+
break
33+
fheight, fwidth, _ = rframe.shape
34+
pad = max(int(cwidth) - fwidth, 0)
35+
writer.write('"')
36+
for j in range(fheight-1):
37+
for i in range(fwidth):
38+
pixel = rframe[j][i]
39+
r, g, b = pixel_to_rgb(pixel)
40+
writer.write("%s" % int(r/comp))
41+
writer.write("%s" % int(g/comp))
42+
writer.write("%s" % int(b/comp))
43+
writer.write('",\n')
44+
writer.flush()
45+
writer.write('""\n')
46+
writer.write(" ],\n")
47+
writer.write('"frame_width":%s,\n' % fwidth)
48+
writer.write('"frame_height":%s\n' % fheight)
49+
writer.write("}\n")
50+
writer.flush()

video_utils.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import cv2
2+
3+
4+
def resize_frame(frame, view_width, view_height):
5+
height, width, _ = frame.shape
6+
reduction_factor = (float(view_height)) / height * 100
7+
reduced_width = int(width * reduction_factor / 100)
8+
reduced_height = int(height * reduction_factor / 100)
9+
dim = (reduced_width, reduced_height)
10+
resized_frame = cv2.resize(frame, dim, interpolation=cv2.INTER_LINEAR)
11+
return resized_frame
12+
13+
14+
def pixel_to_rgb(pixel):
15+
bgr = tuple(float(x) for x in pixel[:3])
16+
return tuple(reversed(bgr))
17+
18+
19+
def get_video(filename):
20+
return cv2.VideoCapture(filename)
21+
22+
23+
def get_video_props(cap):
24+
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
25+
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
26+
length = cap.get(cv2.CAP_PROP_FRAME_COUNT)
27+
fps = cap.get(cv2.CAP_PROP_FPS)
28+
return width, height, length, fps
29+
30+
31+
def get_frame(cap, view_width=None, view_height=None):
32+
while cap.isOpened():
33+
_ret, frame = cap.read()
34+
if frame is None:
35+
break
36+
else:
37+
if view_height is None or view_width is None:
38+
yield frame
39+
else:
40+
yield resize_frame(frame, view_width, view_height)

0 commit comments

Comments
 (0)