CeuiLiSA / Pixiv-Shaft

Pixiv第三方Android客户端
MIT License
4.23k stars 183 forks source link

保存图片为gif功能改进 #118

Open crmmc opened 4 years ago

crmmc commented 4 years ago

gif因为格式问题导致导出的动图质量损失严重,可以使用ffmpeg将图片批量合成mp4小视频代替动图,这样导出的动图很小,画质也会有很大提高! ffmpeg -r 帧率 -i ./%06d.jpg out.mp4 更新了1.9.9在我的UNNO P8设备上保存gif还是有几率闪退,系统是安卓7.1.1。

CeuiLiSA commented 3 years ago

我在mac上用ffmpeg 将图片合成视频,码率低的话,生成的视频文件小但是很模糊。码率拉到10000,视频终于清晰了,但是生成的文件又很大。你的视频又小又清晰是设置了什么特殊参数吗

crmmc commented 3 years ago

你好,首先,要去ffmpeg的官网下载最新版的ffmpeg发行版,之后: 使用命令:ffmpeg -r 帧率 -i ./%06d.jpg -vcodec libx264 -crf 23 out.mp4 解释:使用libx264编码器,crf自定义质量编码模式 设置为23的话效率最高(耗时和质量比值最小,我自己喜欢用的参数)这样编码出来的mp4应该是最优的,这样来保存动图可以几乎原质量恢复出来。gif图片因为格式问题,既耗空间又严重损失质量,还是推荐作者考虑一下输出动图为mp4(x264编码) 可以自己编译ffmpeg,取消掉大部分没用的tag,只保留libx264编码器和png,jpeg编码器(不需要编码声音,全部取消),这样就很小了(记得静态编译) 谢谢

CeuiLiSA commented 3 years ago

我用你的参数试了下,生成的文件很小了,我之前生成的3.1Mb, 用你的参数生成的是500KB,但是播放不了。是不是编码格式的问题导致没法播放,不管mac还是发送给手机都没法播放

crmmc commented 3 years ago

是吗,我是这样使用的: 先使用nhder下载一个gif图 解压zip包,根据1000/压缩包上标注的每张画面所占的毫秒数 获取帧率 使用ffmpeg压缩成视频

附上我用的全自动合成脚本(不是专业人士,代码凌乱见谅)

!/bin/env python3

import os,glob TEMP_DIR = '/opt/pixiv/temp/' OUT_DIR = '/opt/PIXIV_MP4/' SCAN_DIR = '/opt/pixiv/' if not os.path.exists(TEMP_DIR): os.mkdir(TEMP_DIR)

i = glob.glob('*.zip')

i = [] if os.path.exists(SCAN_DIR): os.system('find {} -name "*.zip" >zip.list'.format(SCAN_DIR)) i = open('zip.list','r').read().split('\n') print ('Scan out [{}] Files!'.format(len(i))) for a in i: if a.find('@') > -1: b = a[a.rfind('/') + 1:] print ('Start with {} --> {}'.format(a,b)) ID = int(b[:b.find(')')][b.find('(') + 1:]) NIF= b[b.find(')') + 1:].split('@') name = NIF[0] rate = int(1000/int(NIF[1].replace('ms.zip','')))

os.system('rm -rf /sdcard/Pictures/PixivMP4/temp/*.jpg')

    if os.system("7za x '{}' -o{}".format(a,TEMP_DIR)) == 0:
        if os.system('ffmpeg -n -i "{}%06d.jpg" -loglevel error -r {} "{}{}.mp4"'.format(TEMP_DIR,rate,OUT_DIR,name)) == 0:
            os.remove(a)
        else:
            print ('Faild! {}'.format(a))
    os.system('rm -rf {}*.jpg'.format(TEMP_DIR))

最后,请观察ffmpeg的合成过程有没有报错(冒红字就是出错了)有些动图压缩包里的图片是有问题的(不知道是损坏还是有意而为之)100张图里有几张分辨率是有问题的,然而ffmpeg是自动根据识别到的第一张图设置输出的视频分辨率,有这问题会输出一个1k的视频加上报错,视频无法播放。可能这也是导致shaft前期输出gif或者播放gif闪退的原因(我猜测) 最后还不行的话,请尝试更换播放器,VLC或mpv就不错

SodaWithoutSparkles commented 3 years ago

@crmmc 可以用code block 框住代码,利用三个backtick,就是esc键下面那个。 ```code```

soloopooo commented 3 years ago

可以试试apng,如果有人对动图质量要求很高,而且不需要直接分享的话,apng不失为一种好选择。webp也可以列入可选名单,但是支持动webp的似乎就只剩chrome了...

soloopooo commented 3 years ago

可以试试apng,如果有人对动图质量要求很高,而且不需要直接分享的话,apng不失为一种好选择。webp也可以列入可选名单,但是支持动webp的似乎就只剩chrome了...

另,可以为专业用户开启高级设置按钮。其中可以包含使用的编码(x264,x265等等),码率或者CRF之类的。

sunbeams001 commented 3 years ago

我找到一个绝妙的方案,测试过可以用了,就是目前没想好改在哪里,谁有精力可以搞搞 ffmpeg.exe -f concat -i frames.txt -vcodec libx264 -vsync vfr -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" output.mp4 https://trac.ffmpeg.org/wiki/Slideshow Concat demuxer p.s. duration单位是秒