Browse Source

compress webshots as jpg, other small enhancements

Mike L 4 years ago
parent
commit
68e4755b55
3 changed files with 19 additions and 11 deletions
  1. 7 4
      dist/webshot.js
  2. 4 2
      package.json
  3. 8 5
      src/webshot.ts

+ 7 - 4
dist/webshot.js

@@ -6,6 +6,7 @@ const fs_1 = require("fs");
 const html_entities_1 = require("html-entities");
 const pngjs_1 = require("pngjs");
 const puppeteer = require("puppeteer");
+const sharp = require("sharp");
 const loggers_1 = require("./loggers");
 const mirai_1 = require("./mirai");
 const writeOutTo = (path, data) => new Promise(resolve => {
@@ -25,7 +26,8 @@ class Webshot extends CallableInstance {
     constructor(outDir, mode, onready) {
         super('webshot');
         this.renderWebshot = (url, height, webshotDelay) => {
-            const writeOutPic = (pic) => writeOutTo(`${this.outDir}/${url.replace(/[:\/]/g, '_')}.png`, pic);
+            const jpeg = (data) => data.pipe(sharp()).jpeg({ quality: 90, trellisQuantisation: true });
+            const writeOutPic = (pic) => writeOutTo(`${this.outDir}/${url.replace(/[:\/]/g, '_')}.jpg`, pic);
             const promise = new Promise(resolve => {
                 const width = 1080;
                 logger.info(`shooting ${width}*${height} webshot for ${url}`);
@@ -52,6 +54,7 @@ class Webshot extends CallableInstance {
                         .then(screenshot => {
                         new pngjs_1.PNG({
                             filterType: 4,
+                            deflateLevel: 0,
                         }).on('parsed', function () {
                             // remove comment area
                             let boundary = null;
@@ -102,14 +105,14 @@ class Webshot extends CallableInstance {
                                     this.data = this.data.slice(0, (this.width * boundary) << 2);
                                     this.height = boundary;
                                 }
-                                writeOutPic(this.pack()).then(path => {
+                                writeOutPic(jpeg(this.pack())).then(path => {
                                     logger.info(`finished webshot for ${url}`);
                                     resolve({ path, boundary });
                                 });
                             }
                             else if (height >= 8 * 1920) {
                                 logger.warn('too large, consider as a bug, returning');
-                                writeOutPic(this.pack()).then(path => {
+                                writeOutPic(jpeg(this.pack())).then(path => {
                                     resolve({ path, boundary: 0 });
                                 });
                             }
@@ -149,7 +152,7 @@ class Webshot extends CallableInstance {
                 resolve();
             });
         }).then(data => {
-            const imgName = `${tag}${baseName(url.replace(/(\.[a-z]+)(:.*)/, '$1$2$1'))}`;
+            const imgName = `${tag}${baseName(url.replace(/(\.[a-z]+):(.*)/, '$1__$2$1'))}`;
             return writeOutTo(`${this.outDir}/${imgName}`, data);
         });
         mkdirP(this.outDir = outDir);

+ 4 - 2
package.json

@@ -34,18 +34,20 @@
     "html-entities": "^1.3.1",
     "log4js": "^6.3.0",
     "mirai-ts": "^0.3.1",
-    "pngjs": "^3.3.3",
+    "pngjs": "^5.0.0",
     "puppeteer": "^2.1.0",
     "read-all-stream": "^3.1.0",
     "sha1": "^1.1.1",
+    "sharp": "^0.25.4",
     "twitter": "^1.7.1",
     "typescript": "^2.9.2"
   },
   "devDependencies": {
     "@types/node": "^10.17.27",
-    "@types/pngjs": "^3.3.2",
+    "@types/pngjs": "^3.4.2",
     "@types/puppeteer": "^1.5.0",
     "@types/redis": "^2.8.6",
+    "@types/sharp": "^0.25.0",
     "tslint": "^5.10.0",
     "tslint-config-prettier": "^1.13.0"
   }

+ 8 - 5
src/webshot.ts

@@ -5,12 +5,13 @@ import { XmlEntities } from 'html-entities';
 import { PNG } from 'pngjs';
 import * as puppeteer from 'puppeteer';
 import { Browser } from 'puppeteer';
+import * as sharp from 'sharp';
 import { Stream } from 'stream';
 
 import { getLogger } from './loggers';
 import { MessageChain, MiraiMessage as Message } from './mirai';
 
-const writeOutTo = (path: string, data: PNG | Stream) =>
+const writeOutTo = (path: string, data: Stream) =>
   new Promise<string>(resolve => {
     data.pipe(createWriteStream(path)).on('close', () => resolve(path));
   });
@@ -52,7 +53,8 @@ class Webshot extends CallableInstance<[number], Promise<void>> {
   }
 
   private renderWebshot = (url: string, height: number, webshotDelay: number): Promise<string> => {
-    const writeOutPic = (pic: PNG) => writeOutTo(`${this.outDir}/${url.replace(/[:\/]/g, '_')}.png`, pic);
+    const jpeg = (data: Stream) => data.pipe(sharp()).jpeg({quality: 90, trellisQuantisation: true});
+    const writeOutPic = (pic: Stream) => writeOutTo(`${this.outDir}/${url.replace(/[:\/]/g, '_')}.jpg`, pic);
     const promise = new Promise<{ path: string, boundary: null | number }>(resolve => {
       const width = 1080;
       logger.info(`shooting ${width}*${height} webshot for ${url}`);
@@ -79,6 +81,7 @@ class Webshot extends CallableInstance<[number], Promise<void>> {
             .then(screenshot => {
               new PNG({
                 filterType: 4,
+                deflateLevel: 0,
               }).on('parsed', function () {
                 // remove comment area
                 let boundary = null;
@@ -129,13 +132,13 @@ class Webshot extends CallableInstance<[number], Promise<void>> {
                     this.height = boundary;
                   }
 
-                  writeOutPic(this.pack()).then(path => {
+                  writeOutPic(jpeg(this.pack())).then(path => {
                     logger.info(`finished webshot for ${url}`);
                     resolve({path, boundary});
                   });
                 } else if (height >= 8 * 1920) {
                   logger.warn('too large, consider as a bug, returning');
-                  writeOutPic(this.pack()).then(path => {
+                  writeOutPic(jpeg(this.pack())).then(path => {
                     resolve({path, boundary: 0});
                   });
                 } else {
@@ -173,7 +176,7 @@ class Webshot extends CallableInstance<[number], Promise<void>> {
         resolve();
       });
     }).then(data => {
-      const imgName = `${tag}${baseName(url.replace(/(\.[a-z]+)(:.*)/, '$1$2$1'))}`;
+      const imgName = `${tag}${baseName(url.replace(/(\.[a-z]+):(.*)/, '$1__$2$1'))}`;
       return writeOutTo(`${this.outDir}/${imgName}`, data);
     })