File size: 3,079 Bytes
5cef10e
67b7e1c
5cef10e
 
 
 
 
 
1e768bf
65a0a47
 
67b7e1c
 
5cef10e
 
 
 
 
 
67b7e1c
 
 
65a0a47
 
c0bb512
 
 
5cef10e
c0bb512
 
65a0a47
 
 
 
 
 
5cef10e
 
 
 
 
 
 
 
 
 
 
65a0a47
5cef10e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65a0a47
 
 
 
 
5cef10e
 
65a0a47
 
67b7e1c
 
 
 
 
 
 
 
 
5cef10e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { initFolders } from "./initFolders.mts"
import express from "express"
import fileUpload from "express-fileupload"
import path from "path"
import os from "os"
import fs from "fs"
import extract from "extract-zip"
import archiver from "archiver"

import { runGaussianSplattingCUDA, Options } from "./gaussian-splatting.mts"

initFolders()

declare module 'express-serve-static-core' {
  interface Request {
    files: any;
  }
}

const app = express()
const port = 7860

const maxActiveRequests = 4
let activeRequests = 0

app.use(express.json({limit: '50mb'}))
app.use(express.urlencoded({limit: '50mb', extended: true}))
app.use(fileUpload())

app.post("/", async (req, res) => {
  if(activeRequests >= maxActiveRequests) {
    res.status(503).json({message: "Service Unavailable: Max concurrent requests reached. Please try again later"}).end();
    return
  }
  activeRequests++
  
  if (!req.files || !req.files.data) {
    res.status(400).json({error: "Missing data file in request"}).end()
    return
  }

  let options: Options = req.body // Other parameters come in the body
  let dataFile: fileUpload.UploadedFile = req.files.data

  let inputTempDir = path.join(os.tmpdir(), Math.random().toString().slice(2))
  let outputTempDir = path.join(os.tmpdir(), Math.random().toString().slice(2))

  try {
    fs.mkdirSync(inputTempDir) // Create input temp directory
    fs.mkdirSync(outputTempDir) // Create output temp directory

    await dataFile.mv(path.join(inputTempDir, dataFile.name)) // Move zip file to input temp directory
    await extract(path.join(inputTempDir, dataFile.name), {dir: inputTempDir}) // Unzip file

    fs.unlinkSync(path.join(inputTempDir, dataFile.name)) // Delete zip file after extracting

    options.dataPath = inputTempDir // Set dataPath to temporary directory
    options.outputPath = outputTempDir // Set outputPath to temporary directory

    const result = await runGaussianSplattingCUDA(options)

    // Create a zip file of the output directory
    let outputFilePath = path.join(outputTempDir, 'output.zip')
    let output = fs.createWriteStream(outputFilePath)
    let archive = archiver('zip')

    archive.directory(outputTempDir, false)
    archive.pipe(output)
    await archive.finalize()

    // Send zip file in response
    res.status(200)
    res.download(outputFilePath, 'output.zip', (error) => {
      if (!error) fs.rmSync(inputTempDir, {recursive: true, force: true}) // Delete input temp directory after sending response
      fs.rmSync(outputTempDir, {recursive: true, force: true}) // Delete output temp directory after sending response
    })
  } catch (error) {
    res.status(500).json({
      error: "Couldn't generate gaussian splatting scene",
      message: error
    }).end()
  } finally {
    activeRequests--
  }
});

app.get("/", async (req, res) => {
  res.status(200)
  res.write(`<html><head></head><body>
Splatter API is a micro-service used to generate gaussian splatting scenes.
    </body></html>`)
  res.end()
})

app.listen(port, () => { console.log(`Open http://localhost:${port}`) })