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

How I speed up icons generation process. #328

Open
devalexqt opened this issue Apr 4, 2021 · 0 comments
Open

How I speed up icons generation process. #328

devalexqt opened this issue Apr 4, 2021 · 0 comments

Comments

@devalexqt
Copy link

This favicon module require up to 30 seconds to generate all icons and splash screens on my VPS server (4 core, 8G ram), but I likely decrease converting speed to 3 seconds. (10X improving!)

I do it for my personal use, but if someone interesting to implement this in favicon module, I will be happy to explain.

Generating icons

First of all I use ffmpeg lib with next pattern: one input -> multiple output.
I install ffmpeg via standard OS package manager (It's install old version of ffmpeg v3.2.15, but we not need something special and old version will be ok to use):
sudo apt-get install ffmpeg

And next key step is to follow one input -> multiple output ffmpeg pattern. As short example, now I showing how to generate 2 output icons 50x50 and 100x100: (in real world we need to generate all icons sizes dynamically)

ffmpeg -i favicon.png -filter_complex '[0:v]split=2[icon1][icon2];[icon1]scale=50:50[out1];[icon2]scale=100:100[out2]' \
             -q 32 -y\
             -map [out1] out/favicon_50x50.png\
             -map [out2] out/favicon_100x100.png

And next step It's just execute this command from node.js process.

var { stdout, stderr } = await exec('ffmpeg .......')

As result we will have in out folder a lot of icons.

Generating splash screens

This process little bit tricky. We need fill background color and place our app icon at center. To do so I use standard ffmpeg options:
for filled background I use next ffmpeg filters as input (for example generate 3000x3000 green rectangle):

`ffmpeg -i  -f lavfi -i color=c=green:s=3000x3000 -filter_complex '...'`  

And next step is to use ffmpeg overlay filter to place our app icon at the center of our background rectangle. (in real world we need to generate series of splash screens dynamically)

ffmpeg -i favicon.png -i  -f lavfi -i color=c=green:s=3000x3000 -filter_complex "[0:v]scale=100:100[out_icon];[1:v]scale=1920:1080[out_bg];[out_bg][out_icon]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[overlay_out]" -map [overlay_out] -vframes 1 -q 32 -y out/splash.png 

And after executing next command it we will have series of splash screens:

var { stdout, stderr } = await exec('ffmpeg .......')

favicons-ffmpeg

Real world code

async function(){
        console.log(">>favicon:",options)
        //create list of icons
        const list_icons=[
            ...pushIconsToList(icons.android),
            ...pushIconsToList(icons.appleIcon),
            ...pushIconsToList(icons.coast),
            ...pushIconsToList(icons.favicons),
            ...pushIconsToList(icons.firefox),
            ...pushIconsToList(icons.windows),
            ...pushIconsToList(icons.yandex),
        ]

        //splash screen settings:
        const splash_color_bg="#1abc9c"
        const splash_icon_size="200:200"
        const list_splashscreen=[
            ...pushIconsToList(icons.appleStartup),
        ]

        //generate icons
        var { stdout, stderr } = await exec(`mkdir -p ${options.out} && ffmpeg -noautorotate -threads ${os.cpus().length} -i ${options.favicon} -filter_complex '[0:v]split=${list_icons.length}${list_icons.map((i,index)=>`[icon${index}]`).join("")};${list_icons.map((i,index)=>`[icon${index}]scale=${i.width}:${i.height}[out${index}]`)}'\
            -q 32 -y\
            ${list_icons.map((i,index)=>`-map [out${index}] ${options.out}/${i.name}`).join(" ")}
        `.replace(/\s\s\s+/g," ").replace(/\s\s+/g," "))
        console.log('stdout:', stdout);
        console.error('stderr:', stderr);

        //generate splash screens
        var { stdout, stderr } = await exec(`mkdir -p ${options.out} && ffmpeg -noautorotate -threads ${os.cpus().length} -i ${options.favicon} -f lavfi -i color=c=${splash_color_bg}:s=3000x3000 -filter_complex '[0:v]scale=${splash_icon_size},split=${list_splashscreen.length}${list_splashscreen.map((i,index)=>`[icon${index}]`).join("")};[1:v]split=${list_splashscreen.length}${list_splashscreen.map((i,index)=>`[splash${index}]`).join("")};${list_splashscreen.map((i,index)=>`[splash${index}]scale=${i.width}:${i.height}[splashout${index}]`).join(";")};${list_splashscreen.map((i,index)=>`[splashout${index}][icon${index}]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[overlay${index}]`).join(";")}'\
            -q 32 -y\
            ${list_splashscreen.map((i,index)=>`-map [overlay${index}] -vframes 1 ${options.out}/${i.name}`).join(" ")}
        `.replace(/\s\s\s+/g," ").replace(/\s\s+/g," "))
        console.log('stdout2:', stdout);
        console.error('stderr2:', stderr);        

    }//function 

//create list of icons
function pushIconsToList(icons){
    const list_icons=[]
    for(let [key,value] of Object.entries(icons)){
        list_icons.push({
            name:key,
            width:value.width||64,
            height:value.height||64,
        })
    }//for
    return list_icons
}//pushIconsToList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant