Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

下载下来的动态图的zip压缩包,如何将里面图片还原或制作成动图,并且将画质损耗降到最低呢 #13

Open
MROrangeFanta opened this issue May 27, 2019 · 27 comments
Labels
enhancement New feature or request gugugu Have been gugugued

Comments

@MROrangeFanta
Copy link

我应该用什么程序制作呢,目前我能够操作的软件只能做到30帧甚至不到,或者画质变的很差,而且都是转化成gif格式,怎么才能做成用PixivAnimatDownloader下载的html那样高品质的格式呢?

@Tsuk1ko
Copy link
Owner

Tsuk1ko commented May 29, 2019

貌似 PixivAnimatDownloader 没有开源,无法得知其使用了什么方法

不过 pixiv plus 脚本使用了 gif.js,你可以看一下它的转换效果如何

这个功能可以在后续版本中加入

@Tsuk1ko Tsuk1ko added the enhancement New feature or request label May 29, 2019
@Tsuk1ko
Copy link
Owner

Tsuk1ko commented May 29, 2019

不过 gif 格式动图本来的体积就很大,十分大,这也是为什么从p站下载到的动图是分成每一帧的,p站实际上是将这些 jpg 图片放在 canvas 中按设定好的帧率切换而已

一个十几 MB 的 gif,如果拆分成 jpg 或者使用 mp4 之类的视频格式储存,可能就 1MB 不到

如果一定要减小 gif 体积,必定要牺牲像素数、帧数、色彩数等

@MROrangeFanta
Copy link
Author

效果是不错,下载的动图体积不到2倍,色彩也没有太大的丢失,缺点是帧数轻微变低,导致动画时长略微变长。

增加这个功能的话应该不错,对于科学上网网速捉鸡的人(我)可以先下载后预览一下,再决定是否去下载原图,而且gif图也能更方便的在移动端上分享(至少我的手机打不开html文件)

目前的话,相比 pixiv plus,还是PixivAnimatDownloader更加适合用来下载p站动图。(不用一直开着该动图的网页)

最后,pxder非常棒非常好用,比心(′▽`ʃ♡ƪ)

@Tsuk1ko
Copy link
Owner

Tsuk1ko commented May 29, 2019

@MROrangeFanta 谢谢😆

@LCYLYM
Copy link

LCYLYM commented Jun 19, 2019

那大佬考不考虑加个下载时自动转gif功能呢QAQ

@Tsuk1ko
Copy link
Owner

Tsuk1ko commented Jun 19, 2019

@LCYLYM 在计划中,当然具体更新可能要到7月多,打算重写一个 GUI 版 GUI 咕了

@LCYLYM
Copy link

LCYLYM commented Jun 20, 2019 via email

@LCYLYM
Copy link

LCYLYM commented Jun 22, 2019

@LCYLYM 在计划中,当然具体更新可能要到7月多,打算重写一个 GUI 版

唔。。。求下载收藏时能保存下。。不要每次下载收藏都得重新收集。。。

@Tsuk1ko Tsuk1ko added the help wanted Extra attention is needed label Aug 26, 2019
@Tsuk1ko
Copy link
Owner

Tsuk1ko commented Aug 26, 2019

象征性的更新一下进度

因为 gif.js 只能在浏览器环境下使用,所以我又找了可以在 node 端使用的 gif-encoder,它本身也是 gif.js 的一个 fork

按理来说它们的效果应该是几乎一样的,但 gif-encoder 生成的实际上比 gif.js 生成的大了 30% 左右,唯一和质量有关的参数也是一样的,很怪

pxder/src/zip2gif.js

Lines 1 to 54 in 3e4269f

const ETL = require('etl');
const Unzipper = require('unzipper');
const getPixels = require('get-pixels');
const GifEncoder = require('gif-encoder');
const Fs = require('fs');
const Path = require('path');
async function extractZip(path) {
let promises = [];
await Fs.createReadStream(path)
.pipe(Unzipper.Parse())
.pipe(
ETL.map(entry => {
promises.push(entry.buffer());
entry.autodrain();
})
)
.promise();
return Promise.all(promises);
}
function getPixelsPromise(buffer, mime) {
return new Promise((resolve, reject) => {
getPixels(buffer, mime, (err, pixels) => {
if (err) reject(err);
else resolve(pixels);
});
});
}
async function zip2gif(zipPath, gifPath, mime, delay) {
const gifStream = Fs.createWriteStream(gifPath);
let gif;
const imgs = await extractZip(zipPath);
for (let img of imgs) {
const {
data,
shape: [width, height],
} = await getPixelsPromise(img, mime);
if (!gif) {
gif = new GifEncoder(width, height);
gif.pipe(gifStream);
gif.setDelay(delay);
// gif.setQuality(1000);
gif.setRepeat(0);
gif.writeHeader();
}
gif.addFrame(data);
gif.read();
}
gif.finish();
}
zip2gif('./test/dl/PID/(65123727)miku 吃瓜@80ms.zip', './test/test.gif', 'image/jpeg', 80);

每次看到生成这么鬼大的 gif 真是想咕咕咕,gif 已经很落后了,说到底为什么国内聊天软件还不考虑将 mp4 作为动图表情格式的一种

@LCYLYM
Copy link

LCYLYM commented Aug 27, 2019

GIF。。。。感觉还好吧。。而且现在动图还是占大部分的啊。。。mp4表情没那么快普及吧。。QAQ

@Tsuk1ko
Copy link
Owner

Tsuk1ko commented Aug 27, 2019

@LCYLYM 唉,等一个思想进步,学学 telegram(

@LCYLYM
Copy link

LCYLYM commented Aug 27, 2019

5)PDHOVHSFWW6P~QX2BBJ15

@LCYLYM
Copy link

LCYLYM commented Aug 27, 2019

@LCYLYM唉,等一个思想进步,学学电报(

需要挺多时间的吧。。现在大量表情都是gif。。。。。而且gif还是很多人用的-_-||

@LCYLYM
Copy link

LCYLYM commented Aug 27, 2019

象征性的更新一下进度

因为gif.js只能在浏览器环境下使用,所以我又找了可以在node端使用的gif-encoder,它本身也是gif.js的一个fork

按理来说它们的效果应该是几乎一样的,但gif-encoder生成的实际上比gif.js生成的大了30%左右,唯一和质量有关的参数也是一样的,很怪

pxder/src/zip2gif.js

Lines 1 to 54 in 3e4269f

const ETL = require('etl');
const Unzipper = require('unzipper');
const getPixels = require('get-pixels');
const GifEncoder = require('gif-encoder');
const Fs = require('fs');
const Path = require('path');
async function extractZip(path) {
let promises = [];
await Fs.createReadStream(path)
.pipe(Unzipper.Parse())
.pipe(
ETL.map(entry => {
promises.push(entry.buffer());
entry.autodrain();
})
)
.promise();
return Promise.all(promises);
}
function getPixelsPromise(buffer, mime) {
return new Promise((resolve, reject) => {
getPixels(buffer, mime, (err, pixels) => {
if (err) reject(err);
else resolve(pixels);
});
});
}
async function zip2gif(zipPath, gifPath, mime, delay) {
const gifStream = Fs.createWriteStream(gifPath);
let gif;
const imgs = await extractZip(zipPath);
for (let img of imgs) {
const {
data,
shape: [width, height],
} = await getPixelsPromise(img, mime);
if (!gif) {
gif = new GifEncoder(width, height);
gif.pipe(gifStream);
gif.setDelay(delay);
// gif.setQuality(1000);
gif.setRepeat(0);
gif.writeHeader();
}
gif.addFrame(data);
gif.read();
}
gif.finish();
}
zip2gif('./test/dl/PID/(65123727)miku 吃瓜@80ms.zip', './test/test.gif', 'image/jpeg', 80);

每次看到生成这么鬼大的gif真是想咕咕咕,gif已经很落后了,说到底为什么国内聊天软件还不考虑将mp4作为动图表情格式的一种

所以现在可以自动转gif了咩QAQ

@Tsuk1ko
Copy link
Owner

Tsuk1ko commented Aug 27, 2019

@LCYLYM 目前状况是这样的,就算按最好情况来算,gif.js 生成的千夜画的 Miku 吃瓜gif就有4.6MB了,毕竟原图分辨率也比较高,这种大小gif根本没办法直接拿去QQ发

如果你想缩减大小,最好的选择是降低分辨率,但这个在node上想实现非常麻烦,要用数个第三方包,而且为了处理图像这些包还要引入预构建的可执行文件,这让本来很轻巧的程序变得很庞大,但明明就只为了这一个功能而已,我觉得很不值,不如交给专门做这个工作的软件来处理

@LCYLYM
Copy link

LCYLYM commented Aug 27, 2019 via email

@KagurazakaShirosatosu
Copy link

KagurazakaShirosatosu commented Aug 29, 2019

qwq
如果想要无损的话不如尝试一下手动使用ffmpeg把压缩包里面的图片生成mp4?
我目前所使用的ffmpeg指令是 ffmpeg -r 30 -i ./%06d.jpg 1.mp4
把压缩包里面的图片解压之后cd过去运行就可以了。
其中 -r 30 指帧率为30,可以改成其他的;

ffmpeg也可以将mp4转成gif,指令是
ffmpeg -i xxx.mp4 -s 640x480 -r 15 xxx.gif

@Tsuk1ko
Copy link
Owner

Tsuk1ko commented Aug 30, 2019

@luobogao 可以,有空我看看 node 有没有合适的 ffmpeg 的封装

@darkskygit
Copy link

前阵子看到有人做了个把游戏cg压成视频的工具,不过好像没开源,我问问作者有没有兴趣加上把序列帧压成视频的功能🤔

@darkskygit
Copy link

大概把下载的图全部压成视频也没问题,cg压缩了因为还可以解压出来

@KagurazakaShirosatosu
Copy link

象征性的更新一下进度
因为gif.js只能在浏览器环境下使用,所以我又找了可以在node端使用的gif-encoder,它本身也是gif.js的一个fork
按理来说它们的效果应该是几乎一样的,但gif-encoder生成的实际上比gif.js生成的大了30%左右,唯一和质量有关的参数也是一样的,很怪

pxder/src/zip2gif.js

Lines 1 to 54 in 3e4269f

const ETL = require('etl');
const Unzipper = require('unzipper');
const getPixels = require('get-pixels');
const GifEncoder = require('gif-encoder');
const Fs = require('fs');
const Path = require('path');
async function extractZip(path) {
let promises = [];
await Fs.createReadStream(path)
.pipe(Unzipper.Parse())
.pipe(
ETL.map(entry => {
promises.push(entry.buffer());
entry.autodrain();
})
)
.promise();
return Promise.all(promises);
}
function getPixelsPromise(buffer, mime) {
return new Promise((resolve, reject) => {
getPixels(buffer, mime, (err, pixels) => {
if (err) reject(err);
else resolve(pixels);
});
});
}
async function zip2gif(zipPath, gifPath, mime, delay) {
const gifStream = Fs.createWriteStream(gifPath);
let gif;
const imgs = await extractZip(zipPath);
for (let img of imgs) {
const {
data,
shape: [width, height],
} = await getPixelsPromise(img, mime);
if (!gif) {
gif = new GifEncoder(width, height);
gif.pipe(gifStream);
gif.setDelay(delay);
// gif.setQuality(1000);
gif.setRepeat(0);
gif.writeHeader();
}
gif.addFrame(data);
gif.read();
}
gif.finish();
}
zip2gif('./test/dl/PID/(65123727)miku 吃瓜@80ms.zip', './test/test.gif', 'image/jpeg', 80);

每次看到生成这么鬼大的gif真是想咕咕咕,gif已经很落后了,说到底为什么国内聊天软件还不考虑将mp4作为动图表情格式的一种

所以现在可以自动转gif了咩QAQ

毕竟gif不用审核就能发布

@Skimige
Copy link

Skimige commented Mar 6, 2020

感觉转成 webm 或者 mp4 之类的挺香的… ffmpeg 可以直接调用(让用户自己去下x

@Tsuk1ko
Copy link
Owner

Tsuk1ko commented Mar 6, 2020

感觉转成 webm 或者 mp4 之类的挺香的… ffmpeg 可以直接调用(让用户自己去下x

原本确实是这么打算的,但是由于自己现在也不怎么用 pxder 了,没有动力去写新功能了

image

@LCYLYM
Copy link

LCYLYM commented Mar 7, 2020 via email

@LCYLYM
Copy link

LCYLYM commented Mar 7, 2020 via email

@LCYLYM
Copy link

LCYLYM commented Mar 13, 2020

主要是下载下来很多压缩包希望能批量转或者批量从p站直接下下来gif,主要是自己看。。

@ak1ra-komj
Copy link

ak1ra-komj commented Dec 19, 2021

写了段 bash 脚本 调用 ffmpeg 来转换成 .mp4, 直接用了压缩包文件名中的 delay 值配置帧率, 在 pxder 的下载目录执行脚本就好了, 用了 findparallel 进行批量转换.

@Tsuk1ko Tsuk1ko removed the help wanted Extra attention is needed label Jun 1, 2023
@Tsuk1ko Tsuk1ko added help wanted Extra attention is needed gugugu Have been gugugued and removed help wanted Extra attention is needed labels Jun 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request gugugu Have been gugugued
Projects
None yet
Development

No branches or pull requests

7 participants