add video timeline player and demo
This commit is contained in:
parent
3551e73249
commit
8521eb36ba
5 changed files with 1347 additions and 14 deletions
11
demos/videotimelineplayer/index.html
Normal file
11
demos/videotimelineplayer/index.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>OxJS Video Timeline Player Demo</title
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
|
<script type="text/javascript" src="../../dev/Ox.js"></script>
|
||||||
|
<script type="text/javascript" src="js/demo.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
77
demos/videotimelineplayer/js/demo.js
Normal file
77
demos/videotimelineplayer/js/demo.js
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
Ox.load('UI', function() {
|
||||||
|
|
||||||
|
Ox.Theme('modern');
|
||||||
|
|
||||||
|
var $innerPanel = Ox.SplitPanel({
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
element: Ox.Element(),
|
||||||
|
resizable: true,
|
||||||
|
resize: [64, 128, 192],
|
||||||
|
size: 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
element: Ox.Element()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
orientation: 'vertical'
|
||||||
|
}),
|
||||||
|
$outerPanel = Ox.SplitPanel({
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
element: Ox.Element(),
|
||||||
|
resizable: true,
|
||||||
|
resize: [128, 256, 384],
|
||||||
|
size: 128
|
||||||
|
},
|
||||||
|
{
|
||||||
|
element: $innerPanel
|
||||||
|
}
|
||||||
|
],
|
||||||
|
orientation: 'horizontal'
|
||||||
|
}).appendTo(Ox.$body);
|
||||||
|
|
||||||
|
Ox.get('srt/0097514.srt', function(srt) {
|
||||||
|
|
||||||
|
var $videoTimelinePlayer = Ox.VideoTimelinePlayer({
|
||||||
|
duration: 3029.96,
|
||||||
|
getFrameURL: function(position) {
|
||||||
|
return 'http://0xdb.org/0097514/64p' + position + '.jpg'
|
||||||
|
},
|
||||||
|
getImageURL: function(i) {
|
||||||
|
return 'http://0xdb.org/0097514/timeline64p' + i + '.png'
|
||||||
|
},
|
||||||
|
height: window.innerHeight - 65,
|
||||||
|
paused: true,
|
||||||
|
position: 1000,
|
||||||
|
subtitles: Ox.parseSRT(srt),
|
||||||
|
timelineURL: 'http://0xdb.org/0097514/timeline16p.png',
|
||||||
|
videoRatio: 1.291667,
|
||||||
|
videoURL: 'http://0xdb.org/0097514/96p.webm',
|
||||||
|
width: window.innerWidth - 129
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
resizeend: function(data) {
|
||||||
|
Ox.print('RESIZE', data.size)
|
||||||
|
$videoTimelinePlayer.options({
|
||||||
|
height: data.size
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$innerPanel
|
||||||
|
.replaceElement(1, $videoTimelinePlayer)
|
||||||
|
.bindEvent({
|
||||||
|
resize: function(data) {
|
||||||
|
Ox.print('RESIZE', data.size)
|
||||||
|
$videoTimelinePlayer.options({
|
||||||
|
width: data.size
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$videoTimelinePlayer.gainFocus();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
710
demos/videotimelineplayer/srt/0097514.srt
Normal file
710
demos/videotimelineplayer/srt/0097514.srt
Normal file
|
@ -0,0 +1,710 @@
|
||||||
|
1
|
||||||
|
00:00:00,680 --> 00:00:04,389
|
||||||
|
Change nothing
|
||||||
|
so that everything is different.
|
||||||
|
|
||||||
|
2
|
||||||
|
00:00:24,560 --> 00:00:27,120
|
||||||
|
Don't show every side of things.
|
||||||
|
|
||||||
|
3
|
||||||
|
00:00:27,680 --> 00:00:30,672
|
||||||
|
Allow yourself
|
||||||
|
a margin of indefiniteness.
|
||||||
|
|
||||||
|
4
|
||||||
|
00:05:11,960 --> 00:05:16,272
|
||||||
|
Histories of cinema,
|
||||||
|
in the plural.
|
||||||
|
|
||||||
|
5
|
||||||
|
00:05:27,000 --> 00:05:29,719
|
||||||
|
All the stories
|
||||||
|
|
||||||
|
6
|
||||||
|
00:05:30,680 --> 00:05:33,240
|
||||||
|
that will be
|
||||||
|
|
||||||
|
7
|
||||||
|
00:05:34,560 --> 00:05:36,118
|
||||||
|
that have been.
|
||||||
|
|
||||||
|
8
|
||||||
|
00:09:06,760 --> 00:09:10,878
|
||||||
|
To tell the story of the last tycoon
|
||||||
|
|
||||||
|
9
|
||||||
|
00:09:12,480 --> 00:09:13,754
|
||||||
|
Irving Thalberg.
|
||||||
|
|
||||||
|
10
|
||||||
|
00:09:17,000 --> 00:09:21,835
|
||||||
|
A TV executive has, at most,
|
||||||
|
200 films a year in his head.
|
||||||
|
|
||||||
|
11
|
||||||
|
00:09:23,160 --> 00:09:25,799
|
||||||
|
Thalberg was the only person who,
|
||||||
|
|
||||||
|
12
|
||||||
|
00:09:26,000 --> 00:09:28,958
|
||||||
|
every day, had 52 films in his head.
|
||||||
|
|
||||||
|
13
|
||||||
|
00:10:50,440 --> 00:10:51,839
|
||||||
|
The foundation.
|
||||||
|
|
||||||
|
14
|
||||||
|
00:10:52,880 --> 00:10:54,598
|
||||||
|
The founding father.
|
||||||
|
|
||||||
|
15
|
||||||
|
00:11:02,720 --> 00:11:04,119
|
||||||
|
The only son.
|
||||||
|
|
||||||
|
16
|
||||||
|
00:11:10,200 --> 00:11:12,839
|
||||||
|
This story had to pass by this:
|
||||||
|
|
||||||
|
17
|
||||||
|
00:11:14,960 --> 00:11:17,872
|
||||||
|
A young body,
|
||||||
|
fragile and beautiful,
|
||||||
|
|
||||||
|
18
|
||||||
|
00:11:29,160 --> 00:11:31,674
|
||||||
|
as described
|
||||||
|
F. Scott Fitzgerald -
|
||||||
|
|
||||||
|
19
|
||||||
|
00:11:32,000 --> 00:11:35,072
|
||||||
|
so that this could exist:
|
||||||
|
|
||||||
|
20
|
||||||
|
00:11:38,160 --> 00:11:39,752
|
||||||
|
The power of Hollywood.
|
||||||
|
|
||||||
|
21
|
||||||
|
00:13:22,800 --> 00:13:25,075
|
||||||
|
The power of Babylon.
|
||||||
|
|
||||||
|
22
|
||||||
|
00:13:38,480 --> 00:13:39,879
|
||||||
|
A dream factory.
|
||||||
|
|
||||||
|
23
|
||||||
|
00:13:43,320 --> 00:13:45,231
|
||||||
|
History of cinema.
|
||||||
|
|
||||||
|
24
|
||||||
|
00:13:48,080 --> 00:13:51,470
|
||||||
|
Newness of history.
|
||||||
|
History of news.
|
||||||
|
|
||||||
|
25
|
||||||
|
00:15:59,920 --> 00:16:03,799
|
||||||
|
What has gone through cinema
|
||||||
|
and is still marked by it
|
||||||
|
|
||||||
|
26
|
||||||
|
00:16:04,000 --> 00:16:06,150
|
||||||
|
can no longer enter anywhere else.
|
||||||
|
|
||||||
|
27
|
||||||
|
00:16:10,240 --> 00:16:12,196
|
||||||
|
A dream factory.
|
||||||
|
|
||||||
|
28
|
||||||
|
00:16:22,800 --> 00:16:27,112
|
||||||
|
Communism wore itself out
|
||||||
|
trying to dream up such factories.
|
||||||
|
|
||||||
|
29
|
||||||
|
00:17:46,520 --> 00:17:50,638
|
||||||
|
Married to one of
|
||||||
|
the prettiest women alive.
|
||||||
|
|
||||||
|
30
|
||||||
|
00:18:07,440 --> 00:18:10,034
|
||||||
|
Or to tell the story of Howard Hughes.
|
||||||
|
|
||||||
|
31
|
||||||
|
00:18:35,720 --> 00:18:37,517
|
||||||
|
Braver than Mermoz,
|
||||||
|
|
||||||
|
32
|
||||||
|
00:18:38,200 --> 00:18:39,792
|
||||||
|
richer than Rockefeller.
|
||||||
|
|
||||||
|
33
|
||||||
|
00:19:13,400 --> 00:19:16,790
|
||||||
|
<i>Producer of Citizen Kane,
|
||||||
|
president of TWA.</i>
|
||||||
|
|
||||||
|
34
|
||||||
|
00:19:17,800 --> 00:19:21,270
|
||||||
|
As if Meliès ran Gallimard
|
||||||
|
and the SNCF.
|
||||||
|
|
||||||
|
35
|
||||||
|
00:19:55,680 --> 00:19:57,398
|
||||||
|
And before Hughes Aircraft
|
||||||
|
|
||||||
|
36
|
||||||
|
00:19:57,600 --> 00:20:02,116
|
||||||
|
began fishing up CIA submarines
|
||||||
|
from the bottom of the Pacific,
|
||||||
|
|
||||||
|
37
|
||||||
|
00:20:07,800 --> 00:20:11,793
|
||||||
|
he forced RKO starlets
|
||||||
|
to go on weekly limousine rides
|
||||||
|
|
||||||
|
38
|
||||||
|
00:20:16,560 --> 00:20:18,039
|
||||||
|
at one mile an hour
|
||||||
|
|
||||||
|
39
|
||||||
|
00:20:22,640 --> 00:20:26,110
|
||||||
|
so their breasts
|
||||||
|
wouldn't bounce up and down.
|
||||||
|
|
||||||
|
40
|
||||||
|
00:20:35,640 --> 00:20:38,598
|
||||||
|
His death, worse than anything
|
||||||
|
|
||||||
|
41
|
||||||
|
00:20:38,800 --> 00:20:41,519
|
||||||
|
Defoe had imagined for Robinson.
|
||||||
|
|
||||||
|
42
|
||||||
|
00:23:06,840 --> 00:23:11,277
|
||||||
|
To tell the stories
|
||||||
|
of all the films never made...
|
||||||
|
|
||||||
|
43
|
||||||
|
00:24:08,240 --> 00:24:12,791
|
||||||
|
To tell the stories
|
||||||
|
of all the films never made...
|
||||||
|
|
||||||
|
44
|
||||||
|
00:25:52,200 --> 00:25:55,875
|
||||||
|
To tell the stories
|
||||||
|
of all the films never made,
|
||||||
|
|
||||||
|
45
|
||||||
|
00:26:02,360 --> 00:26:04,271
|
||||||
|
rather than those that were.
|
||||||
|
|
||||||
|
46
|
||||||
|
00:26:11,800 --> 00:26:14,268
|
||||||
|
Those that were
|
||||||
|
can be seen on TV.
|
||||||
|
|
||||||
|
47
|
||||||
|
00:26:14,480 --> 00:26:16,675
|
||||||
|
Let's not exaggerate:
|
||||||
|
|
||||||
|
48
|
||||||
|
00:26:16,880 --> 00:26:19,997
|
||||||
|
They're not even
|
||||||
|
copies of reproductions.
|
||||||
|
|
||||||
|
49
|
||||||
|
00:27:19,800 --> 00:27:23,679
|
||||||
|
<i>1940. Geneva.
|
||||||
|
L'Ecole des femmes. Max Ophuls.</i>
|
||||||
|
|
||||||
|
50
|
||||||
|
00:27:55,080 --> 00:27:57,719
|
||||||
|
He fell on Madeleine Ozeray's ass,
|
||||||
|
|
||||||
|
51
|
||||||
|
00:27:57,920 --> 00:28:01,799
|
||||||
|
while the Germans were taking
|
||||||
|
the French from behind
|
||||||
|
|
||||||
|
52
|
||||||
|
00:28:04,920 --> 00:28:07,718
|
||||||
|
and while Louis Jouvet was giving up.
|
||||||
|
|
||||||
|
53
|
||||||
|
00:29:28,280 --> 00:29:31,078
|
||||||
|
Theater is something
|
||||||
|
too much known.
|
||||||
|
|
||||||
|
54
|
||||||
|
00:29:32,200 --> 00:29:34,839
|
||||||
|
The cinématographe, too unknown...
|
||||||
|
|
||||||
|
55
|
||||||
|
00:29:35,720 --> 00:29:36,675
|
||||||
|
up to now.
|
||||||
|
|
||||||
|
56
|
||||||
|
00:31:29,680 --> 00:31:33,514
|
||||||
|
History of cinema
|
||||||
|
newness of history.
|
||||||
|
|
||||||
|
57
|
||||||
|
00:31:33,720 --> 00:31:35,438
|
||||||
|
History of news.
|
||||||
|
|
||||||
|
58
|
||||||
|
00:31:37,160 --> 00:31:40,914
|
||||||
|
Histories of cinema, with "s".
|
||||||
|
|
||||||
|
59
|
||||||
|
00:31:41,520 --> 00:31:43,033
|
||||||
|
With SS.
|
||||||
|
|
||||||
|
60
|
||||||
|
00:32:21,160 --> 00:32:23,310
|
||||||
|
1939, 1940, 1941...
|
||||||
|
|
||||||
|
61
|
||||||
|
00:32:23,720 --> 00:32:25,472
|
||||||
|
Betrayal by radio,
|
||||||
|
|
||||||
|
62
|
||||||
|
00:32:26,200 --> 00:32:27,872
|
||||||
|
but cinema keeps its word.
|
||||||
|
|
||||||
|
63
|
||||||
|
00:32:37,160 --> 00:32:41,358
|
||||||
|
Because from Siegfried and M
|
||||||
|
to the dictator and Lubitsch,
|
||||||
|
|
||||||
|
64
|
||||||
|
00:32:42,520 --> 00:32:43,873
|
||||||
|
films were made.
|
||||||
|
|
||||||
|
65
|
||||||
|
00:32:48,960 --> 00:32:50,393
|
||||||
|
1940, 1941.
|
||||||
|
|
||||||
|
66
|
||||||
|
00:32:51,240 --> 00:32:55,552
|
||||||
|
Even scratched to death,
|
||||||
|
a simple 35-millimeter rectangle
|
||||||
|
|
||||||
|
67
|
||||||
|
00:32:56,080 --> 00:32:58,640
|
||||||
|
saves the honor of reality.
|
||||||
|
|
||||||
|
68
|
||||||
|
00:33:00,160 --> 00:33:01,991
|
||||||
|
1941, 1942.
|
||||||
|
|
||||||
|
69
|
||||||
|
00:33:02,480 --> 00:33:05,517
|
||||||
|
If poor images still strike
|
||||||
|
|
||||||
|
70
|
||||||
|
00:33:05,920 --> 00:33:09,276
|
||||||
|
without anger or hatred,
|
||||||
|
like a butcher,
|
||||||
|
|
||||||
|
71
|
||||||
|
00:33:10,280 --> 00:33:12,874
|
||||||
|
it is because cinema is there:
|
||||||
|
Silent film,
|
||||||
|
|
||||||
|
72
|
||||||
|
00:33:13,080 --> 00:33:16,959
|
||||||
|
with its humble and formidable
|
||||||
|
power of transfiguration.
|
||||||
|
|
||||||
|
73
|
||||||
|
00:33:19,080 --> 00:33:21,674
|
||||||
|
1942, 1943, 1944.
|
||||||
|
|
||||||
|
74
|
||||||
|
00:33:23,040 --> 00:33:24,758
|
||||||
|
That which plunges into the night
|
||||||
|
|
||||||
|
75
|
||||||
|
00:33:24,960 --> 00:33:27,793
|
||||||
|
is the echo of what silence submerges.
|
||||||
|
|
||||||
|
76
|
||||||
|
00:33:29,960 --> 00:33:31,871
|
||||||
|
What silence submerges
|
||||||
|
|
||||||
|
77
|
||||||
|
00:33:35,240 --> 00:33:38,915
|
||||||
|
sustains in light
|
||||||
|
that which plunges into the night.
|
||||||
|
|
||||||
|
78
|
||||||
|
00:35:43,160 --> 00:35:44,991
|
||||||
|
Images and sounds,
|
||||||
|
|
||||||
|
79
|
||||||
|
00:35:54,320 --> 00:35:56,993
|
||||||
|
like travelers whose paths cross
|
||||||
|
|
||||||
|
80
|
||||||
|
00:35:57,200 --> 00:35:59,156
|
||||||
|
and who can no longer part ways.
|
||||||
|
|
||||||
|
81
|
||||||
|
00:36:35,240 --> 00:36:37,993
|
||||||
|
To prove it, the masses like myths.
|
||||||
|
|
||||||
|
82
|
||||||
|
00:36:38,200 --> 00:36:40,236
|
||||||
|
Cinema speaks to the masses.
|
||||||
|
|
||||||
|
83
|
||||||
|
00:36:41,400 --> 00:36:43,709
|
||||||
|
But if the myth begins with Fantomas,
|
||||||
|
|
||||||
|
84
|
||||||
|
00:36:43,920 --> 00:36:45,512
|
||||||
|
it ends with Christ.
|
||||||
|
|
||||||
|
85
|
||||||
|
00:36:46,520 --> 00:36:49,751
|
||||||
|
What did those who listened
|
||||||
|
to St. Bernard hear?
|
||||||
|
|
||||||
|
86
|
||||||
|
00:36:49,960 --> 00:36:51,996
|
||||||
|
Not what he was saying?
|
||||||
|
|
||||||
|
87
|
||||||
|
00:36:52,200 --> 00:36:54,270
|
||||||
|
Maybe. Probably.
|
||||||
|
|
||||||
|
88
|
||||||
|
00:36:55,920 --> 00:36:58,559
|
||||||
|
How can we neglect what we learn
|
||||||
|
|
||||||
|
89
|
||||||
|
00:36:58,760 --> 00:37:02,548
|
||||||
|
when that unknown voice
|
||||||
|
plunges deep into our hearts?
|
||||||
|
|
||||||
|
90
|
||||||
|
00:37:35,480 --> 00:37:37,914
|
||||||
|
What the news can teach us:
|
||||||
|
|
||||||
|
91
|
||||||
|
00:37:38,840 --> 00:37:41,673
|
||||||
|
The birth of a nation,
|
||||||
|
of hope,
|
||||||
|
|
||||||
|
92
|
||||||
|
00:37:48,760 --> 00:37:50,352
|
||||||
|
of Rome, Open City.
|
||||||
|
|
||||||
|
93
|
||||||
|
00:37:50,560 --> 00:37:53,870
|
||||||
|
The cinématographe
|
||||||
|
never meant to create an event,
|
||||||
|
|
||||||
|
94
|
||||||
|
00:37:54,080 --> 00:37:55,274
|
||||||
|
but a vision.
|
||||||
|
|
||||||
|
95
|
||||||
|
00:38:10,680 --> 00:38:12,272
|
||||||
|
Because the screen
|
||||||
|
|
||||||
|
96
|
||||||
|
00:38:12,480 --> 00:38:13,959
|
||||||
|
is the same white canvas
|
||||||
|
|
||||||
|
97
|
||||||
|
00:38:14,160 --> 00:38:16,151
|
||||||
|
as the Samaritan's shirt.
|
||||||
|
|
||||||
|
98
|
||||||
|
00:38:24,440 --> 00:38:28,149
|
||||||
|
What Arnold and Richter's
|
||||||
|
cameras preserve,
|
||||||
|
|
||||||
|
99
|
||||||
|
00:38:28,840 --> 00:38:32,515
|
||||||
|
so as not to be outdone
|
||||||
|
by nightmares and dreams,
|
||||||
|
|
||||||
|
100
|
||||||
|
00:38:33,080 --> 00:38:37,392
|
||||||
|
will not be shown on a screen,
|
||||||
|
but on a shroud.
|
||||||
|
|
||||||
|
101
|
||||||
|
00:38:44,800 --> 00:38:47,109
|
||||||
|
If the deaths of Puig and the Négus,
|
||||||
|
|
||||||
|
102
|
||||||
|
00:38:47,320 --> 00:38:49,311
|
||||||
|
of Captain Boïeldieu,
|
||||||
|
|
||||||
|
103
|
||||||
|
00:38:49,760 --> 00:38:52,479
|
||||||
|
and of the little bunny
|
||||||
|
were inaudible,
|
||||||
|
|
||||||
|
104
|
||||||
|
00:38:53,280 --> 00:38:56,955
|
||||||
|
it is because life never rendered
|
||||||
|
what it stole from film.
|
||||||
|
|
||||||
|
105
|
||||||
|
00:38:58,360 --> 00:39:02,069
|
||||||
|
Forgetting extermination
|
||||||
|
is part of extermination.
|
||||||
|
|
||||||
|
106
|
||||||
|
00:39:35,400 --> 00:39:36,879
|
||||||
|
Histories of cinema,
|
||||||
|
|
||||||
|
107
|
||||||
|
00:39:37,680 --> 00:39:39,910
|
||||||
|
stories without speech,
|
||||||
|
|
||||||
|
108
|
||||||
|
00:39:40,560 --> 00:39:42,710
|
||||||
|
stories of the night.
|
||||||
|
|
||||||
|
109
|
||||||
|
00:40:12,040 --> 00:40:14,474
|
||||||
|
For nearly 50 years, in the dark,
|
||||||
|
|
||||||
|
110
|
||||||
|
00:40:14,680 --> 00:40:19,151
|
||||||
|
moviegoers burn imagination
|
||||||
|
to heat up reality.
|
||||||
|
|
||||||
|
111
|
||||||
|
00:40:19,760 --> 00:40:21,830
|
||||||
|
Now reality is seeking revenge.
|
||||||
|
|
||||||
|
112
|
||||||
|
00:40:22,040 --> 00:40:24,873
|
||||||
|
It wants real tears, real blood.
|
||||||
|
|
||||||
|
113
|
||||||
|
00:40:32,480 --> 00:40:33,674
|
||||||
|
From Vienna to Madrid,
|
||||||
|
|
||||||
|
114
|
||||||
|
00:40:33,880 --> 00:40:35,108
|
||||||
|
from Siodmak to Capra,
|
||||||
|
|
||||||
|
115
|
||||||
|
00:40:35,320 --> 00:40:37,675
|
||||||
|
from Paris
|
||||||
|
to Los Angeles and Moscow,
|
||||||
|
|
||||||
|
116
|
||||||
|
00:40:37,880 --> 00:40:40,189
|
||||||
|
from Renoir
|
||||||
|
to Malraux and Dovjenko -
|
||||||
|
|
||||||
|
117
|
||||||
|
00:40:40,400 --> 00:40:44,757
|
||||||
|
great fiction directors
|
||||||
|
couldn't control the vengeance
|
||||||
|
|
||||||
|
118
|
||||||
|
00:40:45,520 --> 00:40:48,159
|
||||||
|
which they had directed over and over.
|
||||||
|
|
||||||
|
119
|
||||||
|
00:42:05,120 --> 00:42:07,076
|
||||||
|
The poor cinema of news
|
||||||
|
|
||||||
|
120
|
||||||
|
00:42:07,280 --> 00:42:10,431
|
||||||
|
must clear the blood and tears
|
||||||
|
of all suspicion
|
||||||
|
|
||||||
|
121
|
||||||
|
00:42:10,640 --> 00:42:13,359
|
||||||
|
as streets are cleaned too late,
|
||||||
|
|
||||||
|
122
|
||||||
|
00:42:13,880 --> 00:42:16,519
|
||||||
|
after the army
|
||||||
|
has fired at the masses.
|
||||||
|
|
||||||
|
123
|
||||||
|
00:42:34,320 --> 00:42:35,673
|
||||||
|
What there is of cinema
|
||||||
|
|
||||||
|
124
|
||||||
|
00:42:35,880 --> 00:42:38,678
|
||||||
|
in wartime newsreels
|
||||||
|
says nothing.
|
||||||
|
|
||||||
|
125
|
||||||
|
00:42:38,880 --> 00:42:40,393
|
||||||
|
It does not judge.
|
||||||
|
|
||||||
|
126
|
||||||
|
00:42:53,520 --> 00:42:55,351
|
||||||
|
No close-ups.
|
||||||
|
|
||||||
|
127
|
||||||
|
00:42:55,560 --> 00:42:57,437
|
||||||
|
Suffering is not a star.
|
||||||
|
|
||||||
|
128
|
||||||
|
00:43:02,080 --> 00:43:06,392
|
||||||
|
Nor is the burned-down church
|
||||||
|
or the bombed-out countryside.
|
||||||
|
|
||||||
|
129
|
||||||
|
00:44:02,600 --> 00:44:06,388
|
||||||
|
The spirits of Flaherty and Epstein
|
||||||
|
took over.
|
||||||
|
|
||||||
|
130
|
||||||
|
00:44:06,600 --> 00:44:10,878
|
||||||
|
Daumier and Rembrandt,
|
||||||
|
with his terrifying black and white.
|
||||||
|
|
||||||
|
131
|
||||||
|
00:44:52,600 --> 00:44:54,033
|
||||||
|
A few pans,
|
||||||
|
|
||||||
|
132
|
||||||
|
00:44:54,240 --> 00:44:59,075
|
||||||
|
an occasional high angle, for a mother
|
||||||
|
mourning her murdered child.
|
||||||
|
|
||||||
|
133
|
||||||
|
00:45:45,400 --> 00:45:48,153
|
||||||
|
It is because this time alone
|
||||||
|
|
||||||
|
134
|
||||||
|
00:45:48,840 --> 00:45:53,197
|
||||||
|
the only veritable popular art form
|
||||||
|
rejoins painting,
|
||||||
|
|
||||||
|
135
|
||||||
|
00:45:53,400 --> 00:45:55,118
|
||||||
|
that is: Art.
|
||||||
|
|
||||||
|
136
|
||||||
|
00:45:55,320 --> 00:45:58,392
|
||||||
|
That is: What is reborn
|
||||||
|
from what was burned.
|
||||||
|
|
||||||
|
137
|
||||||
|
00:46:26,640 --> 00:46:30,474
|
||||||
|
We've forgotten that village,
|
||||||
|
its white walls and olive trees,
|
||||||
|
|
||||||
|
138
|
||||||
|
00:46:30,680 --> 00:46:32,432
|
||||||
|
but we remember Picasso,
|
||||||
|
|
||||||
|
139
|
||||||
|
00:46:32,920 --> 00:46:34,558
|
||||||
|
that is: Guernica.
|
||||||
|
|
||||||
|
140
|
||||||
|
00:46:44,120 --> 00:46:48,511
|
||||||
|
We've forgotten Valentin Feldman,
|
||||||
|
killed in '43,
|
||||||
|
|
||||||
|
141
|
||||||
|
00:46:49,320 --> 00:46:52,437
|
||||||
|
but we remember
|
||||||
|
at least one other prisoner,
|
||||||
|
|
||||||
|
142
|
||||||
|
00:46:52,640 --> 00:46:54,119
|
||||||
|
that is: Goya.
|
||||||
|
|
||||||
|
143
|
||||||
|
00:46:55,160 --> 00:46:59,915
|
||||||
|
And if George Stevens hadn't used
|
||||||
|
the first 16-mm color film
|
||||||
|
|
||||||
|
144
|
||||||
|
00:47:00,280 --> 00:47:02,396
|
||||||
|
in Auschwitz and Ravensbruck,
|
||||||
|
|
||||||
|
145
|
||||||
|
00:47:04,040 --> 00:47:08,192
|
||||||
|
Elizabeth Taylor would never
|
||||||
|
have found a place in the sun.
|
||||||
|
|
||||||
|
146
|
||||||
|
00:47:18,920 --> 00:47:20,638
|
||||||
|
1939, 1944.
|
||||||
|
|
||||||
|
147
|
||||||
|
00:47:21,760 --> 00:47:24,832
|
||||||
|
Martyrdom and resurrection
|
||||||
|
of the documentary.
|
||||||
|
|
||||||
|
148
|
||||||
|
00:47:28,600 --> 00:47:32,673
|
||||||
|
How marvelous to be able to look at
|
||||||
|
what we cannot see.
|
||||||
|
|
||||||
|
149
|
||||||
|
00:47:33,040 --> 00:47:35,918
|
||||||
|
What a miracle for our blind eyes.
|
||||||
|
|
||||||
|
150
|
||||||
|
00:47:41,600 --> 00:47:42,749
|
||||||
|
Besides that,
|
||||||
|
|
||||||
|
151
|
||||||
|
00:47:42,960 --> 00:47:44,552
|
||||||
|
cinema is an industry.
|
||||||
|
|
||||||
|
152
|
||||||
|
00:47:45,000 --> 00:47:47,560
|
||||||
|
And if World War I allowed
|
||||||
|
|
||||||
|
153
|
||||||
|
00:47:47,760 --> 00:47:50,228
|
||||||
|
American cinema
|
||||||
|
to ruin French cinema,
|
||||||
|
|
||||||
|
154
|
||||||
|
00:47:50,680 --> 00:47:52,352
|
||||||
|
with the advent of television,
|
||||||
|
|
||||||
|
155
|
||||||
|
00:47:52,560 --> 00:47:54,437
|
||||||
|
World War II allowed it to finance,
|
||||||
|
|
||||||
|
156
|
||||||
|
00:47:55,120 --> 00:47:57,395
|
||||||
|
that is, to ruin, European cinema.
|
||||||
|
|
||||||
|
157
|
||||||
|
00:48:15,200 --> 00:48:17,634
|
||||||
|
"Do you have two hands?"
|
||||||
|
Asks the blind man.
|
||||||
|
|
||||||
|
158
|
||||||
|
00:48:28,320 --> 00:48:31,232
|
||||||
|
But looking won't reassure me.
|
||||||
|
|
||||||
|
159
|
||||||
|
00:48:31,960 --> 00:48:35,430
|
||||||
|
Why trust my eyes, if I have doubts?
|
||||||
|
|
||||||
|
160
|
||||||
|
00:48:36,120 --> 00:48:38,793
|
||||||
|
Why check my eyes
|
||||||
|
|
||||||
|
161
|
||||||
|
00:48:39,000 --> 00:48:41,355
|
||||||
|
to see whether I see my hands?
|
||||||
|
|
||||||
|
162
|
||||||
|
00:49:56,880 --> 00:49:58,518
|
||||||
|
Help!
|
||||||
|
|
|
@ -41,7 +41,8 @@ Ox.BlockVideoTimeline = function(options, self) {
|
||||||
self.$lines = [];
|
self.$lines = [];
|
||||||
self.$tooltip = Ox.Tooltip({
|
self.$tooltip = Ox.Tooltip({
|
||||||
animate: false
|
animate: false
|
||||||
}).css({
|
})
|
||||||
|
.css({
|
||||||
textAlign: 'center'
|
textAlign: 'center'
|
||||||
});
|
});
|
||||||
self.height = 16;
|
self.height = 16;
|
||||||
|
@ -93,7 +94,7 @@ Ox.BlockVideoTimeline = function(options, self) {
|
||||||
self.$lines[i] = $('<div>')
|
self.$lines[i] = $('<div>')
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: (self.margin / 2) + 'px',
|
left: self.margin / 2 + 'px',
|
||||||
top: i * (self.height + self.margin) + 'px',
|
top: i * (self.height + self.margin) + 'px',
|
||||||
width: self.options.width + 'px',
|
width: self.options.width + 'px',
|
||||||
height: '24px',
|
height: '24px',
|
||||||
|
@ -103,7 +104,7 @@ Ox.BlockVideoTimeline = function(options, self) {
|
||||||
self.$images[i] = self.$image.clone()
|
self.$images[i] = self.$image.clone()
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
marginLeft: (-i * self.options.width) + 'px'
|
marginLeft: -i * self.options.width + 'px'
|
||||||
})
|
})
|
||||||
.appendTo(self.$lines[i]);
|
.appendTo(self.$lines[i]);
|
||||||
self.$interfaces[i] = $('<div>')
|
self.$interfaces[i] = $('<div>')
|
||||||
|
@ -113,7 +114,7 @@ Ox.BlockVideoTimeline = function(options, self) {
|
||||||
top: '2px',
|
top: '2px',
|
||||||
width: Math.round(self.options.duration) + 'px',
|
width: Math.round(self.options.duration) + 'px',
|
||||||
height: '20px',
|
height: '20px',
|
||||||
marginLeft: (-i * self.options.width) + 'px',
|
marginLeft: -i * self.options.width + 'px',
|
||||||
//background: 'rgba(255, 0, 0, 0.1)',
|
//background: 'rgba(255, 0, 0, 0.1)',
|
||||||
})
|
})
|
||||||
.appendTo(self.$lines[i]);
|
.appendTo(self.$lines[i]);
|
||||||
|
@ -141,7 +142,8 @@ Ox.BlockVideoTimeline = function(options, self) {
|
||||||
|
|
||||||
function getPosition(e) {
|
function getPosition(e) {
|
||||||
//FIXME: this might still be broken in opera according to http://acko.net/blog/mouse-handling-and-absolute-positions-in-javascript
|
//FIXME: this might still be broken in opera according to http://acko.net/blog/mouse-handling-and-absolute-positions-in-javascript
|
||||||
return (e.offsetX ? e.offsetX : e.clientX - $(e.target).offset().left);
|
return e.offsetX ? e.offsetX
|
||||||
|
: e.clientX - $(e.target).offset().left;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSubtitle(position) {
|
function getSubtitle(position) {
|
||||||
|
@ -188,12 +190,13 @@ Ox.BlockVideoTimeline = function(options, self) {
|
||||||
position = getPosition(e);
|
position = getPosition(e);
|
||||||
subtitle = getSubtitle(position);
|
subtitle = getSubtitle(position);
|
||||||
self.$tooltip.options({
|
self.$tooltip.options({
|
||||||
title: subtitle ?
|
title: subtitle
|
||||||
'<span class=\'OxBright\'>' +
|
? '<span class=\'OxBright\'>' +
|
||||||
Ox.highlight(subtitle.text, self.options.find, 'OxHighlight').replace(/\n/g, '<br/>') +
|
Ox.highlight(subtitle.text, self.options.find, 'OxHighlight').replace(/\n/g, '<br/>') +
|
||||||
'</span><br/>' +
|
'</span><br/>' +
|
||||||
Ox.formatDuration(subtitle['in'], 3) + ' - ' + Ox.formatDuration(subtitle['out'], 3) :
|
Ox.formatDuration(subtitle['in'], 3) + ' - '
|
||||||
Ox.formatDuration(position)
|
+ Ox.formatDuration(subtitle['out'], 3)
|
||||||
|
: Ox.formatDuration(position)
|
||||||
})
|
})
|
||||||
.show(e.clientX, e.clientY);
|
.show(e.clientX, e.clientY);
|
||||||
} else {
|
} else {
|
||||||
|
|
532
source/Ox.UI/js/Video/Ox.VideoTimelinePlayer.js
Normal file
532
source/Ox.UI/js/Video/Ox.VideoTimelinePlayer.js
Normal file
|
@ -0,0 +1,532 @@
|
||||||
|
// vim: et:ts=4:sw=4:sts=4:ft=javascript
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Ox.VideoTimelinePlayer = function(options, self) {
|
||||||
|
|
||||||
|
self = self || {};
|
||||||
|
var that = Ox.Element({}, self)
|
||||||
|
.defaults({
|
||||||
|
cuts: [],
|
||||||
|
duration: 0,
|
||||||
|
find: '',
|
||||||
|
getFrameURL: null,
|
||||||
|
getImageURL: null,
|
||||||
|
height: 0,
|
||||||
|
'in': 0,
|
||||||
|
matches: [],
|
||||||
|
out: 0,
|
||||||
|
paused: false,
|
||||||
|
position: 0,
|
||||||
|
subtitles: [],
|
||||||
|
timelineURL: '',
|
||||||
|
videoRatio: 1,
|
||||||
|
width: 0
|
||||||
|
})
|
||||||
|
.options(options || {})
|
||||||
|
.addClass('OxVideoTimelinePlayer');
|
||||||
|
|
||||||
|
self.fps = 25;
|
||||||
|
self.frame = self.options.position * self.fps;
|
||||||
|
self.frames = self.options.duration * self.fps;
|
||||||
|
self.tileWidth = 1500;
|
||||||
|
self.tileHeight = 64;
|
||||||
|
self.margin = 8;
|
||||||
|
self.contentWidth = self.options.width - 2 * self.margin - Ox.UI.SCROLLBAR_SIZE;
|
||||||
|
self.contentHeight = self.options.height - 32;
|
||||||
|
self.tiles = Math.ceil(self.frames / self.tileWidth);
|
||||||
|
self.videoWidth = Math.round(self.tileHeight * self.options.videoRatio);
|
||||||
|
self.videoLines = getVideoLines();
|
||||||
|
self.lines = getLines();
|
||||||
|
|
||||||
|
self.$topBar = Ox.Bar({size: 16});
|
||||||
|
|
||||||
|
self.$content = Ox.Element()
|
||||||
|
.addClass('OxVideoTimelinePlayer')
|
||||||
|
.css({
|
||||||
|
overflow: 'hidden',
|
||||||
|
overflowY: 'scroll'
|
||||||
|
})
|
||||||
|
.bind({
|
||||||
|
mousedown: mousedown,
|
||||||
|
mouseleave: mouseleave,
|
||||||
|
mousemove: mousemove
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
mousedown: function() {
|
||||||
|
this.gainFocus();
|
||||||
|
},
|
||||||
|
key_down: function() {
|
||||||
|
self.options.position += self.contentWidth / self.fps;
|
||||||
|
setPosition();
|
||||||
|
},
|
||||||
|
key_enter: function() {
|
||||||
|
scrollToPosition();
|
||||||
|
},
|
||||||
|
key_left: function() {
|
||||||
|
self.options.position -= self.videoWidth / self.fps;
|
||||||
|
setPosition();
|
||||||
|
},
|
||||||
|
key_right: function() {
|
||||||
|
self.options.position += self.videoWidth / self.fps;
|
||||||
|
setPosition();
|
||||||
|
},
|
||||||
|
key_shift_left: function() {
|
||||||
|
self.options.position -= 1 / self.fps;
|
||||||
|
setPosition();
|
||||||
|
},
|
||||||
|
key_shift_right: function() {
|
||||||
|
self.options.position += 1 / self.fps;
|
||||||
|
setPosition();
|
||||||
|
},
|
||||||
|
key_space: togglePaused,
|
||||||
|
key_up: function() {
|
||||||
|
self.options.position -= self.contentWidth / self.fps;
|
||||||
|
setPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
self.$bottomBar = Ox.Bar({size: 16});
|
||||||
|
self.$playButton = Ox.Button({
|
||||||
|
style: 'symbol',
|
||||||
|
title: 'play',
|
||||||
|
type: 'image'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
float: 'left'
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
click: togglePaused
|
||||||
|
})
|
||||||
|
.appendTo(self.$bottomBar);
|
||||||
|
self.$muteButton = Ox.Button({
|
||||||
|
style: 'symbol',
|
||||||
|
title: 'mute',
|
||||||
|
type: 'image'
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
float: 'left'
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
|
||||||
|
})
|
||||||
|
.appendTo(self.$bottomBar);
|
||||||
|
self.$smallTimeline = $('<div>')
|
||||||
|
.css({
|
||||||
|
float: 'left',
|
||||||
|
width: self.options.width - 80 + 'px',
|
||||||
|
height: '16px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
background: 'rgb(0, 0, 0)'
|
||||||
|
})
|
||||||
|
.appendTo(self.$bottomBar);
|
||||||
|
self.$smallTimelineImage = $('<img>')
|
||||||
|
.attr({
|
||||||
|
src: self.options.timelineURL
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
width: self.options.width - 96 + 'px',
|
||||||
|
height: '16px',
|
||||||
|
margin: '0 8px 0 8px'
|
||||||
|
})
|
||||||
|
.appendTo(self.$smallTimeline);
|
||||||
|
self.$position = $('<div>')
|
||||||
|
.css({
|
||||||
|
float: 'left',
|
||||||
|
width: '40px',
|
||||||
|
height: '12px',
|
||||||
|
padding: '2px 4px 2px 4px',
|
||||||
|
fontSize: '9px'
|
||||||
|
})
|
||||||
|
.html(Ox.formatDuration(self.options.position))
|
||||||
|
.appendTo(self.$bottomBar);
|
||||||
|
|
||||||
|
self.$panel = Ox.SplitPanel({
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
element: self.$topBar,
|
||||||
|
size: 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
element: self.$content
|
||||||
|
},
|
||||||
|
{
|
||||||
|
element: self.$bottomBar,
|
||||||
|
size: 16
|
||||||
|
}
|
||||||
|
],
|
||||||
|
orientation: 'vertical'
|
||||||
|
});
|
||||||
|
|
||||||
|
that.setElement(self.$panel);
|
||||||
|
|
||||||
|
self.$lines = [];
|
||||||
|
self.$timelines = [];
|
||||||
|
self.$interfaces = [];
|
||||||
|
|
||||||
|
self.$timeline = renderTimeline();
|
||||||
|
//setSubtitles();
|
||||||
|
Ox.loop(self.lines, function(i) {
|
||||||
|
addLine(i);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.$frameBox = $('<div>')
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
top: self.margin / 2 - 1 + 'px',
|
||||||
|
width: self.videoWidth + 'px',
|
||||||
|
height: self.tileHeight + 'px',
|
||||||
|
borderTop: '1px solid rgba(255, 255, 255, 0.5)',
|
||||||
|
borderBottom: '1px solid rgba(255, 255, 255, 0.5)',
|
||||||
|
background: 'rgb(0, 0, 0)'
|
||||||
|
})
|
||||||
|
.appendTo(self.$timelines[self.videoLines[1]][0]);
|
||||||
|
self.$frame = $('<img>')
|
||||||
|
.attr({
|
||||||
|
src: self.options.getFrameURL(self.options.position)
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
width: self.videoWidth + 'px',
|
||||||
|
height: self.tileHeight + 'px',
|
||||||
|
})
|
||||||
|
.appendTo(self.$frameBox)
|
||||||
|
$('<div>')
|
||||||
|
.addClass('OxFrameInterface')
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: self.videoWidth + 'px',
|
||||||
|
height: self.tileHeight + 'px',
|
||||||
|
})
|
||||||
|
.appendTo(self.$frameBox);
|
||||||
|
|
||||||
|
self.$videoBox = $('<div>')
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
top: self.margin / 2 - 1 + 'px',
|
||||||
|
width: self.videoWidth + 'px',
|
||||||
|
height: self.tileHeight + 'px',
|
||||||
|
borderTop: '1px solid rgba(255, 255, 255, 0.5)',
|
||||||
|
borderBottom: '1px solid rgba(255, 255, 255, 0.5)',
|
||||||
|
background: 'rgb(0, 0, 0)',
|
||||||
|
zIndex: 5
|
||||||
|
})
|
||||||
|
.appendTo(self.$timelines[self.videoLines[0]][0]);
|
||||||
|
self.$video = Ox.VideoPlayer({
|
||||||
|
duration: self.options.duration,
|
||||||
|
height: self.tileHeight,
|
||||||
|
paused: self.options.paused,
|
||||||
|
position: self.options.position,
|
||||||
|
scaleToFill: true,
|
||||||
|
video: self.options.videoURL,
|
||||||
|
width: self.videoWidth
|
||||||
|
})
|
||||||
|
.bindEvent({
|
||||||
|
ended: function() {
|
||||||
|
togglePaused(true);
|
||||||
|
},
|
||||||
|
playing: function(data) {
|
||||||
|
self.options.position = data.position;
|
||||||
|
setPosition(true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.appendTo(self.$videoBox);
|
||||||
|
$('<div>')
|
||||||
|
.addClass('OxFrameInterface OxVideoInterface')
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: self.videoWidth + 'px',
|
||||||
|
height: self.tileHeight + 'px',
|
||||||
|
})
|
||||||
|
.appendTo(self.$videoBox);
|
||||||
|
|
||||||
|
self.$tooltip = Ox.Tooltip({
|
||||||
|
animate: false
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
textAlign: 'center'
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
scrollToPosition();
|
||||||
|
});
|
||||||
|
|
||||||
|
function addLine(i) {
|
||||||
|
self.$lines[i] = $('<div>')
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: self.margin + 'px',
|
||||||
|
top: self.margin / 2 + i * (self.tileHeight + self.margin) + 'px',
|
||||||
|
width: self.contentWidth + 'px',
|
||||||
|
height: self.tileHeight + self.margin + 'px',
|
||||||
|
overflowX: 'hidden'
|
||||||
|
})
|
||||||
|
.appendTo(self.$content);
|
||||||
|
self.$timelines[i] = [
|
||||||
|
self.$timeline.clone()
|
||||||
|
.css({
|
||||||
|
width: self.frame + self.videoWidth + 'px',
|
||||||
|
marginLeft: -i * self.contentWidth + 'px',
|
||||||
|
}),
|
||||||
|
self.$timeline.clone()
|
||||||
|
.css({
|
||||||
|
marginLeft: -i * self.contentWidth + self.videoWidth - 1 + 'px',
|
||||||
|
})
|
||||||
|
];
|
||||||
|
self.$lines[i]
|
||||||
|
.append(self.$timelines[i][1])
|
||||||
|
.append(self.$timelines[i][0]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLines() {
|
||||||
|
return Math.ceil((self.frames - 1 + self.videoWidth) / self.contentWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPosition(e) {
|
||||||
|
return (
|
||||||
|
e.offsetX ? e.offsetX
|
||||||
|
: e.clientX - $(e.target).offset().left
|
||||||
|
) / self.fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubtitle(position) {
|
||||||
|
var subtitle = '';
|
||||||
|
Ox.forEach(self.options.subtitles, function(v) {
|
||||||
|
if (v['in'] <= position && v.out > position) {
|
||||||
|
subtitle = v;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return subtitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVideoLine() {
|
||||||
|
self.videoLine = Math.floor(getVideoFrame() / self.contentWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVideoLines() {
|
||||||
|
var videoFrame = getVideoFrame(),
|
||||||
|
videoLeft = videoFrame % self.contentWidth,
|
||||||
|
lines = [];
|
||||||
|
lines[0] = Math.floor(videoFrame / self.contentWidth);
|
||||||
|
lines[1] = lines[0] + (
|
||||||
|
videoLeft + self.videoWidth > self.contentWidth ? 1 : 0
|
||||||
|
)
|
||||||
|
if (videoLeft + Math.floor(self.videoWidth / 2) > self.contentWidth) {
|
||||||
|
lines.reverse();
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVideoFrame() {
|
||||||
|
return Math.floor(self.options.position * self.fps);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mousedown(e) {
|
||||||
|
var $target = $(e.target),
|
||||||
|
isTimeline = $target.is('.OxTimelineInterface'),
|
||||||
|
isVideo = $target.is('.OxFrameInterface');
|
||||||
|
if (isTimeline) {
|
||||||
|
self.options.position = getPosition(e);
|
||||||
|
setPosition();
|
||||||
|
if (!self.triggered) {
|
||||||
|
that.triggerEvent('position', {
|
||||||
|
position: self.options.position
|
||||||
|
});
|
||||||
|
self.triggered = true;
|
||||||
|
setTimeout(function() {
|
||||||
|
self.triggered = false;
|
||||||
|
}, 250);
|
||||||
|
}
|
||||||
|
} else if (isVideo) {
|
||||||
|
togglePaused();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouseleave() {
|
||||||
|
self.$tooltip.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function mousemove(e) {
|
||||||
|
var $target = $(e.target),
|
||||||
|
isTimeline = $target.is('.OxTimelineInterface'),
|
||||||
|
isVideo = $target.is('.OxFrameInterface'),
|
||||||
|
position, subtitle;
|
||||||
|
if (isTimeline || isVideo) {
|
||||||
|
position = isTimeline ? getPosition(e) : self.options.position;
|
||||||
|
subtitle = getSubtitle(position);
|
||||||
|
self.$tooltip.options({
|
||||||
|
title: (
|
||||||
|
subtitle
|
||||||
|
? '<span class=\'OxBright\'>' +
|
||||||
|
Ox.highlight(subtitle.text, self.options.find, 'OxHighlight').replace(/\n/g, '<br/>') +
|
||||||
|
'</span><br/>'
|
||||||
|
: ''
|
||||||
|
) + Ox.formatDuration(position, 3)
|
||||||
|
})
|
||||||
|
.show(e.clientX, e.clientY);
|
||||||
|
} else {
|
||||||
|
self.$tooltip.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTimeline() {
|
||||||
|
var $timeline = $('<div>')
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
width: self.frames + 'px',
|
||||||
|
height: self.tileHeight + self.margin + 'px',
|
||||||
|
overflow: 'hidden'
|
||||||
|
});
|
||||||
|
Ox.loop(self.tiles, function(i) {
|
||||||
|
$('<img>')
|
||||||
|
.attr({
|
||||||
|
src: self.options.getImageURL(i)
|
||||||
|
})
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: i * self.tileWidth + 'px',
|
||||||
|
top: self.margin / 2 + 'px'
|
||||||
|
})
|
||||||
|
.appendTo($timeline);
|
||||||
|
});
|
||||||
|
$('<div>')
|
||||||
|
.addClass('OxTimelineInterface')
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
top: self.margin / 2 + 'px',
|
||||||
|
width: self.frames + 'px',
|
||||||
|
height: self.tileHeight + 'px',
|
||||||
|
//background: 'rgba(255, 0, 0, 0.5)'
|
||||||
|
})
|
||||||
|
.appendTo($timeline);
|
||||||
|
|
||||||
|
return $timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToPosition() {
|
||||||
|
var scrollTop = self.$content.scrollTop(),
|
||||||
|
videoTop = [
|
||||||
|
self.margin + Ox.min(self.videoLines) * (self.tileHeight + self.margin),
|
||||||
|
self.margin + Ox.max(self.videoLines) * (self.tileHeight + self.margin)
|
||||||
|
],
|
||||||
|
offset = self.contentHeight - self.tileHeight - self.margin;
|
||||||
|
if (videoTop[0] < scrollTop + self.margin) {
|
||||||
|
self.$content.scrollTop(videoTop[0] - self.margin);
|
||||||
|
} else if (videoTop[1] > scrollTop + offset) {
|
||||||
|
self.$content.scrollTop(videoTop[1] - offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPosition(fromVideo) {
|
||||||
|
var max, min, videoLines, isPlaying = !self.options.paused;
|
||||||
|
self.options.position = Ox.limit(self.options.position, 0, self.options.duration);
|
||||||
|
self.frame = Math.floor(self.options.position * self.fps);
|
||||||
|
videoLines = getVideoLines();
|
||||||
|
min = Ox.min(Ox.flatten([self.videoLines, videoLines]));
|
||||||
|
max = Ox.max(Ox.flatten([self.videoLines, videoLines]));
|
||||||
|
Ox.loop(min, max + 1, function(i) {
|
||||||
|
self.$timelines[i][0].css({
|
||||||
|
width: self.frame + self.videoWidth + 'px'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (videoLines[1] != self.videoLines[1]) {
|
||||||
|
self.videoLines[1] = videoLines[1];
|
||||||
|
self.$frameBox.detach().appendTo(self.$timelines[videoLines[1]][0]);
|
||||||
|
}
|
||||||
|
if (videoLines[0] != self.videoLines[0]) {
|
||||||
|
self.videoLines[0] = videoLines[0];
|
||||||
|
isPlaying && self.$video.togglePaused();
|
||||||
|
self.$videoBox.detach().appendTo(self.$timelines[videoLines[0]][0]);
|
||||||
|
isPlaying && self.$video.togglePaused();
|
||||||
|
}
|
||||||
|
if (videoLines[0] != videoLines[1]) {
|
||||||
|
self.$frame.attr({
|
||||||
|
src: self.options.getFrameURL(
|
||||||
|
self.paused
|
||||||
|
? self.options.position
|
||||||
|
: Math.floor(self.options.position)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.videoLines = videoLines;
|
||||||
|
if (!fromVideo) {
|
||||||
|
self.$video.options({position: self.options.position});
|
||||||
|
self.$frame.attr({
|
||||||
|
src: self.options.getFrameURL(self.options.position)
|
||||||
|
});
|
||||||
|
scrollToPosition();
|
||||||
|
}
|
||||||
|
self.$position.html(Ox.formatDuration(self.options.position))
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSubtitles() {
|
||||||
|
self.$timeline.find('.OxSubtitle').remove();
|
||||||
|
self.$subtitles = [];
|
||||||
|
self.options.subtitles.forEach(function(subtitle, i) {
|
||||||
|
var found = self.options.find
|
||||||
|
&& subtitle.text.toLowerCase().indexOf(self.options.find.toLowerCase()) > -1;
|
||||||
|
self.$subtitles[i] = $('<div>')
|
||||||
|
.addClass('OxSubtitle' + (found ? ' OxHighlight' : ''))
|
||||||
|
.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: (subtitle['in'] * self.fps) + 'px',
|
||||||
|
width: (((subtitle.out - subtitle['in']) * self.fps) - 2) + 'px'
|
||||||
|
})
|
||||||
|
.html(Ox.highlight(subtitle.text, self.options.find, 'OxHighlight'))
|
||||||
|
.appendTo(self.$timeline);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setWidth() {
|
||||||
|
self.contentWidth = self.options.width - 2 * self.margin - Ox.UI.SCROLLBAR_SIZE;
|
||||||
|
self.lines = getLines();
|
||||||
|
Ox.loop(self.lines, function(i) {
|
||||||
|
if (self.$lines[i]) {
|
||||||
|
self.$lines[i].css({
|
||||||
|
width: self.contentWidth + 'px'
|
||||||
|
});
|
||||||
|
self.$timelines[i][0].css({
|
||||||
|
marginLeft: -i * self.contentWidth + 'px'
|
||||||
|
});
|
||||||
|
self.$timelines[i][1].css({
|
||||||
|
marginLeft: -i * self.contentWidth + self.videoWidth + 'px'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addLine(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
while (self.$lines.length > self.lines) {
|
||||||
|
self.$lines[self.$lines.length - 1].remove();
|
||||||
|
self.$lines.pop();
|
||||||
|
self.$timelines.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function togglePaused(fromVideo) {
|
||||||
|
self.options.paused = !self.options.paused;
|
||||||
|
!fromVideo && self.$video.options({
|
||||||
|
paused: self.options.paused
|
||||||
|
});
|
||||||
|
self.$playButton.options({
|
||||||
|
title: !self.options.paused ? 'pause' : 'play'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.setOption = function(key, value) {
|
||||||
|
if (key == 'width') {
|
||||||
|
setWidth();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return that;
|
||||||
|
|
||||||
|
};
|
Loading…
Reference in a new issue