0 Votes

Wiki source code of VideoUpload

Last modified by Ryan C on 2025/03/07 23:43

Show last authors
1 {{include reference="XWikiTubeCode.Macros"/}}
2
3 {{velocity}}
4 #* Upload and transcode files *#
5 #set($videoUploader = $xwiki.parseGroovyFromPage("XWikiTubeCode.VideoUploadGroovy"))
6 #set($discard = $videoUploader.init($xwiki, $xcontext, $services))
7 #set($discard = $xcontext.put("videoUploader", $videoUploader))
8 #set($action = $request.action)
9
10 #if ("$!action" != '')
11 #if ($action == "uploadVideo")
12 ## Check the video target document
13 #set($targetDocRef = "")
14 #if ("$!request.targetDocRef" != '' && $xwiki.exists($request.targetDocRef))
15 #set($targetDocRef = $request.targetDocRef)
16 #end
17 #set($rep = $videoUploader.uploadVideo("videoInput", $targetDocRef))
18 #if ($rep.ret == true)
19 ## Display video information
20 #displayVideoInfo($rep.video)
21 ## Encode the video
22 #set($ffmpeg = $videoUploader.mediaTranscoder.checkFFmpeg())
23 #if ($ffmpeg)
24 #set($video = $rep.video)
25 #set($videoDocRef = $video.videoDocRef)
26 #if("$!videoDocRef" != '' && $xwiki.exists($videoDocRef))
27 #set($discard = $videoUploader.encodeVideo($videoDocRef, "libvpx-vp9"))
28 #set($videoDoc = $xwiki.getDocument($videoDocRef))
29 #set($videoObj = $videoDoc.getObject("XWikiTubeCode.MediaClass", "original", "1"))
30 #if("$!videoObj" != '')
31 #set($discard = $videoObj.set("encoded", 1))
32 #set($discard = $videoDoc.save())
33 #end
34 #end
35 #end
36 #else
37 #if($rep.error == "file_exists")
38 {{warning}}The video name alreay exists.{{/warning}}
39 #end
40 #end
41 #elseif($action == 'getXWikiTubeVideos')
42 ## List all XWiki videos filtred by user
43 #set($offset = $mathtool.toInteger($request.get('offset')))
44 #set($offset = $offset - 1)
45 #if($offset < 0)
46 #set($offset = 0)
47 #end
48 #set($limit = $mathtool.toInteger($request.get('limit')))
49 #if(!$hasAdmin)
50 #set($userFilter = " and doc.author=${xcontext.user}")
51 #end
52 #set($filterName = "$!{request.get('name')}")
53 #if("$!filterName" != '')
54 #set($filterNameCond = " and media.name like :filterName")
55 #end
56 #set($xwql = "from doc.object(XWikiTubeCode.MediaClass) as media where doc.fullName<>'XWikiTubeCode.MediaTemplate' and media.original=1 $!userFilter $!filterNameCond order by doc.creationDate")
57 #set($query = $services.query.xwql($xwql))
58 #if("$!filterName" != '')
59 #set($query = $query.bindValue("filterName","%$filterName%"))
60 #end
61 #set($totalRows = $query.count())
62 ##set($results = $query.setLimit($limit).setOffset($offset).execute())
63 #set($results = $query.execute())
64 #set($returnedRows = $results.size())
65 ## ===
66 ## JSON
67 ## ===
68 #set($rows = [])
69 #foreach($mediaDocRef in $results)
70 #set($mediaDoc = $xwiki.getDocument($mediaDocRef))
71 #set($mediaObj = $mediaDoc.getObject("XWikiTubeCode.MediaClass"))
72 #set($name = $mediaObj.getValue("name"))
73 #set($extension = $mediaObj.getValue("extension"))
74 #set($mimeType = $mediaObj.getValue("mimeType"))
75 #set($size = $mathtool.div($mediaObj.getValue("size"), 1000000))
76 #set($duration = $mediaObj.getValue("duration"))
77 #set($resolution = $mediaObj.getValue("resolution"))
78 #set($creator = $xwiki.getUserName($mediaDoc.author, false))
79 #set($creationDate = $xwiki.formatDate($mediaDoc.creationDate))
80 #set($encoded = "False")
81 #if($mediaObj.getValue("encoded") == "1")
82 #set($encoded = "True")
83 #end
84 #set($mediaURL = $xwiki.getURL($mediaDocRef))
85 #set($actionLinks = "<div class='actionsrow'>")
86 #set($actionLinks = "${actionLinks}<div class='actionsrow'><a href='$mediaURL' rel='${mediaDocRef}' class='glyphicon glyphicon-play' title='Play'></a>")
87 #if($hasAdmin || ($xcontext.user == $mediaDoc.author))
88 #set($actionLinks = "${actionLinks}<a href='javascript:;' rel='${mediaDocRef}' class='glyphicon glyphicon-cog' title='Encode'></a>")
89 #set($actionLinks = "${actionLinks}<a href='javascript:;' rel='${mediaDocRef}' class='glyphicon glyphicon-trash delete-media' title='Delete'></a>")
90 #end
91 #set($actionLinks = "${actionLinks}</div>")
92 #set($row = {"doc_viewable": true, "name": $name, "extension": $extension, "mimeType": $mimeType, "size": "${size} MB", "duration": "${duration} s", "resolution": $resolution, "creator": "$creator", "creationDate": $creationDate, "encoded": $encoded, "actions": $actionLinks})
93 #set($discard = $rows.add($row))
94 #end
95 {
96 "totalrows": $totalRows,
97 "matchingtags": {},
98 "tags" : [],
99 "returnedrows": $returnedRows,
100 "offset": ($offset + 1),
101 "reqNo": $mathtool.toInteger($request.reqNo),
102 "rows": $jsontool.serialize($rows)
103 }
104 #elseif($action == 'deleteMedia')
105 #if("$!request.mediaDocRef" != "" && $xwiki.exists($request.mediaDocRef))
106 #set($mediaDocRef = $request.mediaDocRef)
107 #set($rep = $videoUploader.deleteMedia($mediaDocRef))
108 $rep
109 #end
110 #elseif($action == 'selectVideo')
111 #if("$!request.videoDocRef" != "" && $xwiki.exists($request.videoDocRef))
112 #set($videoDocRef = $request.videoDocRef)
113 #set($videoDoc = $xwiki.getDocument($videoDocRef))
114 #set($attachments = $videoDoc.getAttachmentList())
115 #set($videoAttachments = [])
116 #foreach($att in $attachments)
117 #if($att.getMimeType().contains("video"))
118 #set($discard = $videoAttachments.add($att))
119 #end
120 #end
121 {{html}}#displayVideoEncodeForm($videoAttachments){{/html}}
122 #end
123 #elseif($action == 'initVideoEncoding')
124 #if("$!request.videoDocRef" != '' && $xwiki.exists($request.videoDocRef) && "$!request.videoName" != '')
125 #set($videoDocRef = $request.videoDocRef)
126 #set($videoName = $request.videoName)
127 #set($newLine = $escapetool.getNewline())
128 #set($rep = $videoUploader.encodeAttachmentVideo($videoDocRef, $videoName))
129 #if($rep)
130 $videoUploader.logger.info("${newLine}Video encoding initialization phase succeed, document=${videoDocRef}, video=${videoName}${newLine}")
131 #else
132 $videoUploader.logger.severe("${newLine}Video encoding initialization phase has failed, document=${videoDocRef}, video=${videoName}${newLine}")
133 #end
134 {"initStatus": $rep.ret, "error": "$!rep.error"}
135 #end
136 #elseif($action == 'videoEncode')
137 #if("$!request.videoDocRef" != '' && $xwiki.exists($request.videoDocRef) && "$!request.videoName" != '')
138 #set($videoDocRef = $request.videoDocRef)
139 #set($videoName = $request.videoName)
140 #set($videoDoc = $xwiki.getDocument($videoDocRef))
141 #set($waitingCommands = $videoDoc.getObjects("XWikiTubeCode.CommandClass", "status", "waiting"))
142 #set($completeCommands = $videoDoc.getObjects("XWikiTubeCode.CommandClass", "status", "complete"))
143 #set($noAudioStreamCommands = $videoDoc.getObjects("XWikiTubeCode.CommandClass", "status", "noaudiostream"))
144 #set($noVideoStreamCommands = $videoDoc.getObjects("XWikiTubeCode.CommandClass", "status", "novideostream"))
145 #set($discard = $completeCommands.addAll($noAudioStreamCommands))
146 #set($discard = $completeCommands.addAll($noVideoStreamCommands))
147 #set($runingCommands = $videoDoc.getObjects("XWikiTubeCode.CommandClass", "status", "transcoding"))
148 #set($transcodingErrorCommands = $videoDoc.getObjects("XWikiTubeCode.CommandClass", "status", "transcoding_error"))
149 #set($discard = $runingCommands.addAll($transcodingErrorCommands))
150 #set($newLine = $escapetool.getNewline())
151
152 ## Check waiting commands
153 #set($waitingCmdsJSON = [])
154 #if($waitingCommands.size() > 0)
155 ## Check if there is no runing command and check also if FFmpeg is not runing
156 #set($ffmpegRunning = $videoUploader.mediaTranscoder.checkFFmpegRunning())
157 #if(!$ffmpegRunning && $runingCommands.size() == 0)
158 ## Start a new command
159 #set($nextCmd = $waitingCommands[0])
160 #if($nextCmd.outputFile != "" && !$nextCmd.outputFile.contains("manifest"))
161 ## video and audio streams commands
162 #set($sourceVideoPath = $videoUploader.fileNameUtils.concat($nextCmd.getValue("workDir"), $videoName))
163 #set($commandStatus = "transcoding")
164 #if($nextCmd.outputFile.contains("audio")) ## audio
165 ## Check if the original video has audio stream
166 #if($videoUploader.mediaTranscoder.hasAudioStream($sourceVideoPath))
167 ## Start the command
168 #set($rep = $videoUploader.commandRunner.run(["bash", "-c", $nextCmd.getValue("cmd")], '', 2147483647))
169 $videoUploader.logger.info("${newLine}Start FFmpeg command «${nextCmd.getValue('cmd')}» , document=${videoDocRef}, video=${videoName}${newLine}")
170 #else
171 ## Update the command status to complete
172 #set($commandStatus = "noaudiostream")
173 #end
174 #else
175 ## Check if the original video has video stream
176 #if($videoUploader.mediaTranscoder.hasVideoStream($sourceVideoPath))
177 ## Start the command
178 #set($rep = $videoUploader.commandRunner.run(["bash", "-c", $nextCmd.getValue("cmd")], '', 2147483647))
179 $videoUploader.logger.info("${newLine}Start FFmpeg command «${nextCmd.getValue('cmd')}» , document=${videoDocRef}, video=${videoName}${newLine}")
180 #else
181 ## Update the command status to complete
182 #set($commandStatus = "novideostream")
183 #end
184 #end
185 ## Update the status of the command object
186 #set($cmdObj = $videoDoc.getObject("XWikiTubeCode.CommandClass", "outputFile", $nextCmd.outputFile))
187 #if($cmdObj)
188 #set($discard = $cmdObj.set("status", $commandStatus))
189 #set($discard = $videoDoc.save())
190 #end
191 #elseif($nextCmd.outputFile.contains("manifest"))
192 ## Manifest file command
193 ## Generate the manifest command and update the command object
194 #set($manifestCmd = $videoUploader.mediaTranscoder.generateDASHManifestCommand($nextCmd.getValue("workDir")))
195 #set($rep = $videoUploader.commandRunner.run(["bash", "-c", $manifestCmd], '', 2147483647))
196 $videoUploader.logger.info("${newLine}Start FFmpeg command «${manifestCmd}» , document=${videoDocRef}, video=${videoName}${newLine}")
197 ## Update the status/cmd properties of the command object
198 #set($cmdObj = $videoDoc.getObject("XWikiTubeCode.CommandClass", "outputFile", $nextCmd.outputFile))
199 #if($cmdObj)
200 #set($discard = $cmdObj.set("status", "transcoding"))
201 #set($discard = $cmdObj.set("cmd", $manifestCmd))
202 #set($discard = $videoDoc.save())
203 #end
204 #end
205 #end
206 #foreach($cmd in $waitingCommands)
207 #set($discard = $waitingCmdsJSON.add({"progress": 0, "stream": $cmd.outputFile.replace("_output.txt", "")}))
208 #end
209 #end
210
211 ## Check runing commands
212 #set($encodeError = false)
213 #set($runingCmdsJSON = [])
214 #foreach($cmd in $runingCommands)
215 #set($outputFilePath = "${cmd.workDir}/${cmd.outputFile}")
216 #set($errorFilePath = "${cmd.workDir}/${cmd.outputFile.replace('output', 'error')}")
217 #set($progressRep = $videoUploader.checkEncodingProgress($outputFilePath, $errorFilePath, $cmd.getValue("duration")))
218 #if($progressRep.status == "end") ## Command complete
219 ## Update the command object
220 #set($cmdObj = $videoDoc.getObject("XWikiTubeCode.CommandClass", "outputFile", $cmd.outputFile))
221 #if($cmdObj)
222 #set($discard = $cmdObj.set("status", "complete"))
223 #set($discard = $videoDoc.save())
224 $videoUploader.logger.info("${newLine}FFmpeg command successfully completed «${cmd.getValue('cmd')}» , document=${videoDocRef}, video=${videoName}${newLine}")
225 #end
226 #set($discard = $runingCmdsJSON.add({"progress": 100, "stream": $cmd.outputFile.replace("_output.txt", "")}))
227 #elseif($progressRep.status == "empty_file") ## FFmpeg Error
228 #set($discard = $runingCmdsJSON.add({"progress": 0, "stream": $cmd.outputFile.replace("_output.txt", ""), "error": $!progressRep.error}))
229 #set($encodeError = true)
230 ## Update the command object
231 #set($cmdObj = $videoDoc.getObject("XWikiTubeCode.CommandClass", "outputFile", $cmd.outputFile))
232 #if($cmdObj)
233 #set($discard = $cmdObj.set("status", "transcoding_error"))
234 #set($discard = $videoDoc.save())
235 $videoUploader.logger.severe("${newLine}FFmpeg command error «${cmd.getValue('cmd')}» , document=${videoDocRef}, video=${videoName}, error=$!{progressRep.error}${newLine}")
236 #end
237 #else
238 #set($discard = $runingCmdsJSON.add({"progress": $progressRep.progress, "stream": $cmd.outputFile.replace("_output.txt", "")}))
239 #end
240 #end
241 ##
242
243 ## Check complete commands
244 #set($completeCmdsJSON = [])
245 #foreach($cmd in $completeCommands)
246 #set($discard = $completeCmdsJSON.add({"progress": 100, "stream": $cmd.outputFile.replace("_output.txt", "")}))
247 #end
248 ##
249 $jsontool.serialize({"encodeError": $encodeError, "waitingCmds": $waitingCmdsJSON, "completeCmds": $completeCmdsJSON, "runingCmds": $runingCmdsJSON})
250 #end
251 #elseif($action == 'attachEncodedFiles')
252 #if("$!request.videoDocRef" != '' && $xwiki.exists($request.videoDocRef) && "$!request.videoName" != '')
253 #set($videoDocRef = $request.videoDocRef)
254 #set($videoName = $request.videoName)
255 #set($videoDoc = $xwiki.getDocument($videoDocRef))
256 #set($originalVideoObj = $videoDoc.getObject("XWikiTubeCode.MediaClass", "original", 1))
257 #set($newLine = $escapetool.getNewline())
258 #if($originalVideoObj && $originalVideoObj.getValue("name") == $videoName && $originalVideoObj.getValue("encoded") != 1)
259 ## Start files attachments
260 #set($videoDir = $originalVideoObj.getValue("dirPath"))
261 #set($rep = $videoUploader.attachEncodingFilesToDoc($videoDir, $videoDocRef, $videoName))
262 #if($rep)
263 $videoUploader.logger.info("${newLine}Attaching encoded files to document success: document=$videoDocRef, video=${videoName}${newLine}")
264 #else
265 $videoUploader.logger.severe("${newLine}Attaching encoded files to document fails: document=$videoDocRef, video=${videoName}${newLine}")
266 #end
267 $rep
268 #end
269 #end
270 #end
271 #end
272 {{/velocity}}