]> git.plutz.net Git - rawnet/blob - page_video.sh
status bar for upload
[rawnet] / page_video.sh
1 #!/bin/sh
2
3 # ID    NAME    DESCRIPTION     RESX    RESY    LENGTH  COVER   STATUS (void|private|hidden|public)     UPLOADER        HITS    DESCR_CACHE     FUTUREUSE
4
5 if [ "$video" -a -f "$vid_db" -a -r "$vid_db" ]; then
6   read -r VIDEO_ID VIDEO_NAME VIDEO_DESCRIPTION VIDEO_RESX VIDEO_RESY \
7           VIDEO_LENGTH VIDEO_COVER VIDEO_STATUS VIDEO_UPLOADER VIDEO_HITS \
8           VIDEO_DESCR_CACHE VIDEO_FUTUREUSE <<-EOF
9         $(grep "^${video}       " "${vid_db}")
10         EOF
11   if [ "$VIDEO_ID" ]; then
12            VIDEO_NAME="$(UNSTRING "$VIDEO_NAME")"
13     VIDEO_DESCRIPTION="$(UNSTRING "$VIDEO_DESCRIPTION")"
14           VIDEO_COVER="$(UNSTRING "$VIDEO_COVER")"
15     VIDEO_DESCR_CACHE="$(UNSTRING "$VIDEO_DESCR_CACHE")"
16   else
17     video=''
18   fi
19 fi
20
21 update_video(){
22   local id="${1}" name description resx resy length cover status uploader \
23         hits descr_cache futureuse
24   local ID NAME DESCRIPTION RESX RESY LENGTH COVER STATUS UPLOADER HITS \
25         DESCR_CACHE FUTUREUSE
26   local arg video thumb cnt
27   video="${_DATA}/${CHANNEL_ID}/${VIDEO_ID}.mp4"
28   thumb="${_DATA}/${CHANNEL_ID}/${VIDEO_ID}_thumb.jpg"
29
30   for arg in "$@"; do case $arg in
31     name=*) name="${arg#*=}";;
32     description=*) description="${arg#*=}";;
33     cover=*) cover="${arg#*=}";;
34     status=*) status="${arg#*=}";;
35     uploader=*) uploader="${arg#*=}";;
36     hits=*) hits="${arg#*=}";;
37   esac; done
38
39   if [ -f "$video" -a -r "$video" ]; then
40     arg="$(echo; ffprobe -show_entries format=duration:stream=width,height "$video" 2>&-)"
41     resx="${arg#*width=}"; resx="${resx%%${BR}*}"
42     resy="${arg#*height=}"; resy="${resy%%${BR}*}"
43     length="${arg#*duration=}"; length="${length%%${BR}*}"
44   fi
45   if [ "${length%.*}" -a ! "${thumb}" -nt "${video}" ]; then
46     for cnt in 1 2 3 4 5 6 7 8 9 10; do
47       ffmpeg -nostdin -y -ss "$((cnt * ${length%.*} / 11))" -i "$video" \
48              -frames 1 "${thumb%.jpg}_$((cnt - 1)).jpg"
49     done 2>&-
50     montage "${thumb%.jpg}"_[0-9].jpg \
51             -background "#000000" \
52             -tile 10x1 -geometry 320x180+0+0 \
53             -interlace line -quality 85 "${thumb}"
54     rm -- "${thumb%.jpg}"_[0-9].jpg
55   fi
56
57   if LOCK "$vid_db"; then
58     while read -r ID NAME DESCRIPTION RESX RESY LENGTH COVER STATUS UPLOADER HITS \
59                   DESCR_CACHE FUTUREUSE; do
60       if [ "$id" = "$ID" ]; then
61         printf '%s      %s      %s      %i      %i      %f      %s      %s      %s      %i      %s      %s\n' \
62                "$id" "$(STRING "${name-$(UNSTRING "$NAME")}")" \
63                "$(STRING "${description-$(UNSTRING "$DESCRIPTION")}")" \
64                "${resx:-${resx-${RESX}}${resx+0}}" \
65                "${resy:-${resy-${RESY}}${resy+0}}" \
66                "${length:-${length-${LENGTH}}${length+0}}" \
67                "$(STRING "${cover-$(UNSTRING "$COVER")}")" \
68                "${status:-${status-${STATUS}}${status+void}}" \
69                "${uploader:-${uploader-${UPLOADER}}${uploader+\\}}" \
70                "${hits:-${hits-${HITS}}${hits+0}}" \
71                "$(printf %s "${description-$(UNSTRING "$DESCRIPTION")}" |markdown |STRING)" \
72                "${FUTUREUSE:-\\}"
73       else
74         printf '%s      %s      %s      %i      %i      %f      %s      %s      %s      %i      %s      %s\n' \
75                 "$ID" "$NAME" "$DESCRIPTION" "$RESX" "$RESY" "$LENGTH" \
76                 "$COVER" "$STATUS" "$UPLOADER" "$HITS" "$DESCR_CACHE" \
77                 "$FUTUREUSE"
78       fi
79     done <"$vid_db" >"${vid_db}.$$"
80     mv -- "${vid_db}.$$" "${vid_db}"
81     RELEASE "$vid_db"
82   else
83     return 1
84   fi
85 }
86
87 UPLOAD(){
88   local file="$1"
89   local boundary line length=0
90
91   [ ! "${CONTENT_TYPE}" -o "${CONTENT_TYPE##multipart/form-data;*}" ] && return 1
92
93   boundary="${CONTENT_TYPE#*; boundary=}"
94   boundary="${boundary%%;*}"
95
96   while read -r line; do
97     length="$(( length + ${#line} + 1))"
98     [ "${line%${CR}}" = "--$boundary" ] && break
99   done
100   while read -r line; do
101     length="$(( length + ${#line} + 1))"
102     [ ! "${line%${CR}}" ] && break \
103     || debug "$line"
104   done
105
106   printf "%i\n" "$(( CONTENT_LENGTH - length ))" >"${file}.upload"
107   head -c "$(( CONTENT_LENGTH - length ))" \
108   | sed -nE '
109     # print lines until boundary ( = actual file upload)
110     :FILE; p; n;
111     /^--'"${boundary}"'(--)?\r?$/!bFILE;
112     # discard remaining lines
113     :END; $q; n; bEND;
114   ' >"$file"
115   truncate -s $(( $(stat -c %s -- "$file") -2 )) -- "$file"
116   rm -- "${file}.upload"
117 }
118
119 [ "$REQUEST_METHOD" = POST ] && case "$(POST action)" in
120   update_video)
121     if [ ! "$USER_ID" ]; then
122       REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_NOTLOGGEDIN"
123     elif ! AUTHOR; then
124       REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_UPDATE_NOTALLOWED"
125     elif update_video "$video" "name=$(POST name)" \
126                       "description=$(POST description)" \
127                       "status=$(POST status |grep -m1 -xE 'void|private|hidden|public')" \
128                       "uploader=$USER_ID"; then
129       REDIRECT "${_BASE}/channel/${channel}/${video}/#UPDATE_SUCCESS"
130     else
131       REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_UPDATE_NOLOCK"
132     fi
133     ;;
134   update_video_cancel)
135     REDIRECT "${_BASE}/channel/${channel}/${video}/#CANCELED"
136     ;;
137   delete)
138     if [ ! "$USER_ID" ]; then
139       REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_NOTLOGGEDIN"
140     elif ! AUTHOR; then
141       REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_UPDATE_NOTALLOWED"
142     elif [ "$(POST delconfirm)" != confirm ]; then
143       REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_NOT_CONFIRMED"
144     elif LOCK "$vid_db"; then
145       while read -r id tail; do
146         [ "$id" != "$video" ] && printf '%s     %s\n' "$id" "$tail"
147       done <"$vid_db" >"${vid_db}.$$"
148       mv -- "${vid_db}.$$" "$vid_db"
149       rm -- "${_DATA}/${channel}/${video}.mp4" "${_DATA}/${channel}/${video}_thumb.jpg"
150       RELEASE "$vid_db"
151       REDIRECT "${_BASE}/channel/${channel}/#DELETE_CONFIRM"
152     else
153       REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_UPDATE_NOLOCK"
154     fi
155     ;;
156 esac
157
158 if [ "$REQUEST_METHOD" = POST -a "$channel" -a "$video" ]; then
159   if ! AUTHOR; then
160     head -c "$CONTENT_LENGTH" >/dev/null
161     REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_UPLOAD_NOTALLOWED"
162   elif [ "$VIDEO_STATUS" != void ]; then
163     head -c "$CONTENT_LENGTH" >/dev/null
164     REDIRECT "${_BASE}/channel/${channel}/${video}/#ERROR_UPLOAD_NOCLOBBER"
165   elif UPLOAD "$_DATA/$channel/$video.mp4"; then
166     update_video "$video" status=private
167     VIDEO_STATUS=private
168   fi
169 fi
170
171 if [ "$channel" -a "$video" -a "$action" = edit ]; then
172   AUTHOR || REDIRECT "$_BASE/$channel/$video/#ERROR_EDIT_NOTALLOWED"
173
174   yield_page "$VIDEO_NAME - Edit" "video edit" <<-EOF
175         [form .video .edit method=POST
176           [input name="name" value="$(HTML "$VIDEO_NAME")" placeholder="Video Name"]
177           [fieldset .status $([ $VIDEO_STATUS = void ] && printf "disabled=disabled")
178             [radio "status" "private" #status_private $(checked $VIDEO_STATUS private void)]
179               [label for=status_private tooltip="Video is only visible to channel authors" Private]
180             [radio "status" "hidden" #status_hidden  $(checked $VIDEO_STATUS hidden)]
181               [label for=status_hidden tooltip="Video will not be listed but can be viewed by anyone knowing the URL" Hidden]
182             [radio "status" "public" #status_public $(checked $VIDEO_STATUS public)]
183               [label for=status_public tooltip="Video will be listed publicly" Public]
184           ]
185           [textarea name="description" placeholder="Description" . $(HTML "$VIDEO_DESCRIPTION")]
186           [submit "action" "update_video" . Update]
187           [submit "action" "update_video_cancel" . Cancel]
188           [fieldset .delete
189             [checkbox "delconfirm" "confirm" id="delconfirm"]
190             [label for=delconfirm Delete Video]
191             [submit "action" "delete" Delete Video]
192           ]
193         ]
194         EOF
195
196 elif [ "$channel" -a "$video" -a "$action" = frameuploadprogress ]; then
197   AUTHOR || REDIRECT "$_BASE/$channel/$video/#ERROR_EDIT_NOTALLOWED"
198   printf '%s\r\n' 'Content-Type: text/html' 'Connection: close' ''
199   printf '<!DOCTYPE HTML>
200   <html><head>
201     <title>Upload Progress</title>
202     <style type="text/css"><!--
203     body {
204       text-align: center;
205     }
206     .progress {
207       display: block;
208       position: absolute;
209       width: 20em;
210       background-color: #FFF;
211       border: 1pt solid;
212       border-radius: 4pt;
213       height: 1.25em;
214     }
215     .progress .bar {
216       display: block;
217       position: absolute;
218       left: 0; top: 0; bottom: 0;
219       background-color: #666;
220     }
221     .progress .count {
222       display: block;
223       position: absolute;
224       left: 0; top: 0; right: 0; bottom: 0;
225       line-height: 1.375em;
226     }
227     --></style>
228   </head><body>
229   '
230   printf '<div class=progress><div class=bar style="width: 0%%;"></div><div class=count>%i / %i</div></div>\n' 0 0
231   while [ ! -f "$_DATA/$channel/$video.mp4" -a \
232           ! -f "$_DATA/$channel/$video.mp4.upload" ]; do sleep 1; done
233   read size <"$_DATA/$channel/$video.mp4.upload"
234   while [ -f "$_DATA/$channel/$video.mp4.upload" ]; do
235     stat="$(stat -c %s "$_DATA/$channel/$video.mp4" 2>&-)"
236     printf '<div class=progress><div class=bar style="width:%i%%;"></div><div class=count>%iMB / %iMB</div></div>\n' \
237       "$(( stat * 100 / size ))" "$((stat / 1048576))" "$((size / 1048576))"
238     sleep 1
239   done
240   printf '<span class=progress><div class=bar style="width:100%%;"></div><div class=count>Ready!</div></span>\n'
241   printf '</body></html>'
242
243 elif [ "$channel" -a "$video" -a "$action" = frameupload ]; then
244   AUTHOR || REDIRECT "$_BASE/$channel/$video/#ERROR_EDIT_NOTALLOWED"
245   printf '%s\r\n' 'Content-Type: text/html' ''
246   [ "$VIDEO_STATUS" = void ] && "$_EXEC"/cgilite/html-sh.sed <<-EOF
247         [!DOCTYPE HTML]
248         [html [head
249           [title Upload Form]
250         ][body
251         [form .upload method=POST enctype="multipart/form-data"
252           [input type=file name=upload]
253           [submit "action" "video_upload" Upload]
254         ]
255         ]]
256         EOF
257   [ "$VIDEO_STATUS" != void ] && "$_EXEC"/cgilite/html-sh.sed <<-EOF
258         [!DOCTYPE HTML]
259         [html [head
260           [title Upload Form]
261         ][body
262           [a href="./" target="_parent" . Reload Page!]
263         ]]
264         EOF
265
266 elif [ "$channel" -a "$video" ]; then
267   [ $VIDEO_STATUS = public -o $VIDEO_STATUS = hidden ] || AUTHOR || { . ${_EXEC}/page_404.sh; exit 0; }
268
269   yield_page "$VIDEO_NAME" "video" <<-EOF
270         [nav [a href="../../" Channels] - [a href="../" $(HTML "${CHANNEL_NAME:-(Unnamed Channel)}")] - [span $(HTML "${VIDEO_NAME:-(Unnamed Video)}")]]
271         $( AUTHOR && [ $VIDEO_STATUS = void ] && printf '
272         [iframe src="frameuploadprogress" width="100%%" height="50"
273           [a href="freameuploadprogress" Iframe: Upload progress]
274         ]
275         [iframe src="frameupload" width="100%%" height="50"
276           [form .upload method=POST enctype="multipart/form-data"
277             [input type=file name=upload]
278             [submit "action" "video_upload" Upload]
279           ]
280         ]')
281         $( [ $VIDEO_STATUS != void ] && printf '
282         [video preload=none controls=controls width=%i height=%i
283           [source src="%s/video/%s/%s.mp4" type="video/mp4"]
284         ]' "$VIDEO_RESX" "$VIDEO_RESY" "$_BASE" "$channel" "$video"
285         )
286         $(AUTHOR && printf '[a .button href="edit" edit]')
287         [h1 .name $(HTML "$VIDEO_NAME")]
288         [div .description . ${VIDEO_DESCR_CACHE}]
289         EOF
290
291 else
292   . "$_EXEC/page_404.sh"
293 fi