@@ -28,14 +28,15 @@ import java.nio.file.Files
2828import java.nio.file.Path
2929import java.nio.file.Paths
3030
31- abstract class AbstractPreviewHandler (private val collections : DAO <MediaCollection >, private val itemIndex : DaoIndexer <MediaItem , Pair <UID , String >>, config : Config ) : GetRestHandler<Any>, AccessManagedRestHandler {
31+ abstract class AbstractPreviewHandler (
32+ private val collections : DAO <MediaCollection >,
33+ private val itemIndex : DaoIndexer <MediaItem , Pair <UID , String >>,
34+ config : Config
35+ ) : GetRestHandler<Any>, AccessManagedRestHandler {
3236 override val apiVersion = " v1"
3337 override val permittedRoles = setOf (RestApiRole .VIEWER )
3438 private val cacheLocation = Paths .get(config.cachePath + " /previews" )
3539
36- // private val waitingMap = ConcurrentHashMap<Path, Long>()
37- // private val timeOut = 10_000
38-
3940 protected fun handlePreviewRequest (collectionId : UID , itemName : String , time : Long? , ctx : Context ) {
4041
4142 val item = itemIndex[collectionId to itemName].firstOrNull()
@@ -48,11 +49,13 @@ abstract class AbstractPreviewHandler(private val collections: DAO<MediaCollecti
4849
4950 }
5051
52+ // private val missingImage = this.javaClass.getResourceAsStream("/img/missing.png")!!.readAllBytes()
53+ // private val waitingImage = this.javaClass.getResourceAsStream("/img/loading.png")!!.readAllBytes()
5154
5255 protected fun handlePreviewRequest (item : MediaItem , time : Long? , ctx : Context ) {
5356
5457 val collection = this .collections[item.collection]
55- ? : throw ErrorStatusException (404 , " Collection ${item.collection} does not exist." , ctx)
58+ ? : throw ErrorStatusException (404 , " Collection ${item.collection} does not exist." , ctx)
5659
5760 val basePath = File (collection.basePath)
5861
@@ -81,24 +84,13 @@ abstract class AbstractPreviewHandler(private val collections: DAO<MediaCollecti
8184 if (Files .exists(imgPath)) { // if file is available, send contents immediately
8285 ctx.header(" Cache-Control" , " max-age=31622400" )
8386 ctx.sendFile(imgPath.toFile())
84- }else { // if not, wait for it if necessary
87+ } else { // if not, schedule and return error
8588
8689 FFmpegUtil .extractFrame(Path .of(collection.basePath, item.location), time, imgPath)
87-
88- val future = FFmpegUtil .previewImageStream(imgPath)
89-
90- if (future == null ) { // image does not exist and is not scheduled
91- ctx.status(404 )
92- ctx.header(" Cache-Control" , " max-age=31622400" )
93- ctx.contentType(" image/png" )
94- ctx.result(this .javaClass.getResourceAsStream(" /img/missing.png" )!! )
95- } else {
96- ctx.contentType(" image/jpg" )
97- ctx.future(future)
98- }
90+ ctx.status(408 )
91+ ctx.header(" Cache-Control" , " max-age=30" )
9992
10093 }
101-
10294 }
10395 }
10496
@@ -108,26 +100,34 @@ abstract class AbstractPreviewHandler(private val collections: DAO<MediaCollecti
108100
109101}
110102
111- class MediaPreviewHandler (collections : DAO <MediaCollection >, itemIndex : DaoIndexer <MediaItem , Pair <UID , String >>, config : Config ) : AbstractPreviewHandler(collections, itemIndex, config) {
112-
113- @OpenApi(summary = " Returns a preview image from a collection item" ,
114- path = " /api/v1/preview/item/{collection}/{item}/{time}" ,
115- pathParams = [
116- OpenApiParam (" collectionId" , String ::class , " Unique ID of the collection." ),
117- OpenApiParam (" item" , String ::class , " Name of the MediaItem" ),
118- OpenApiParam (" time" , Long ::class , " Time into the video in milliseconds (for videos only)." )
119- ],
120- tags = [" Media" ],
121- responses = [OpenApiResponse (" 200" , [OpenApiContent (type = " image/png" )]), OpenApiResponse (" 401" ), OpenApiResponse (" 400" )],
122- ignore = true
103+ class MediaPreviewHandler (
104+ collections : DAO <MediaCollection >,
105+ itemIndex : DaoIndexer <MediaItem , Pair <UID , String >>,
106+ config : Config
107+ ) : AbstractPreviewHandler(collections, itemIndex, config) {
108+
109+ @OpenApi(
110+ summary = " Returns a preview image from a collection item" ,
111+ path = " /api/v1/preview/item/{collection}/{item}/{time}" ,
112+ pathParams = [
113+ OpenApiParam (" collectionId" , String ::class , " Unique ID of the collection." ),
114+ OpenApiParam (" item" , String ::class , " Name of the MediaItem" ),
115+ OpenApiParam (" time" , Long ::class , " Time into the video in milliseconds (for videos only)." )
116+ ],
117+ tags = [" Media" ],
118+ responses = [OpenApiResponse (
119+ " 200" ,
120+ [OpenApiContent (type = " image/png" )]
121+ ), OpenApiResponse (" 401" ), OpenApiResponse (" 400" )],
122+ ignore = true
123123 )
124124 override fun get (ctx : Context ) {
125125
126126 try {
127127 val params = ctx.pathParamMap()
128128
129129 val collectionId = params[" collection" ]?.UID ()
130- ? : throw ErrorStatusException (400 , " Collection ID not specified or invalid." , ctx)
130+ ? : throw ErrorStatusException (400 , " Collection ID not specified or invalid." , ctx)
131131 val itemName = params[" item" ] ? : throw ErrorStatusException (400 , " Item name not specified." , ctx)
132132 val time = params[" time" ]?.toLongOrNull()
133133
@@ -147,17 +147,25 @@ class MediaPreviewHandler(collections: DAO<MediaCollection>, itemIndex: DaoIndex
147147}
148148
149149
150- class SubmissionPreviewHandler (collections : DAO <MediaCollection >, itemIndex : DaoIndexer <MediaItem , Pair <UID , String >>, config : Config ) : AbstractPreviewHandler(collections, itemIndex, config) {
151-
152- @OpenApi(summary = " Returns a preview image for a submission" ,
153- path = " /api/v1/preview/submission/{runId}/{submissionId}" ,
154- pathParams = [
155- OpenApiParam (" runId" , String ::class , " Competition Run ID" ),
156- OpenApiParam (" submissionId" , String ::class , " Subission ID" )
157- ],
158- tags = [" Media" ],
159- responses = [OpenApiResponse (" 200" , [OpenApiContent (type = " image/png" )]), OpenApiResponse (" 401" ), OpenApiResponse (" 400" )],
160- ignore = true
150+ class SubmissionPreviewHandler (
151+ collections : DAO <MediaCollection >,
152+ itemIndex : DaoIndexer <MediaItem , Pair <UID , String >>,
153+ config : Config
154+ ) : AbstractPreviewHandler(collections, itemIndex, config) {
155+
156+ @OpenApi(
157+ summary = " Returns a preview image for a submission" ,
158+ path = " /api/v1/preview/submission/{runId}/{submissionId}" ,
159+ pathParams = [
160+ OpenApiParam (" runId" , String ::class , " Competition Run ID" ),
161+ OpenApiParam (" submissionId" , String ::class , " Subission ID" )
162+ ],
163+ tags = [" Media" ],
164+ responses = [OpenApiResponse (
165+ " 200" ,
166+ [OpenApiContent (type = " image/png" )]
167+ ), OpenApiResponse (" 401" ), OpenApiResponse (" 400" )],
168+ ignore = true
161169 )
162170 override fun get (ctx : Context ) {
163171
@@ -187,11 +195,13 @@ class SubmissionPreviewHandler(collections: DAO<MediaCollection>, itemIndex: Dao
187195 if (submission is TemporalSubmissionAspect ) submission.start else null , ctx
188196 )
189197 }
198+
190199 is TextAspect -> {
191200 ctx.header(" Cache-Control" , " max-age=31622400" )
192201 ctx.contentType(" image/png" )
193202 ctx.result(this .javaClass.getResourceAsStream(" /img/text.png" )!! )
194203 }
204+
195205 else -> {
196206 ctx.header(" Cache-Control" , " max-age=31622400" )
197207 ctx.contentType(" image/png" )
0 commit comments