iArt.ai
AI 모션 그래픽 소프트웨어, 누구나 사용할 수 있는 After Effects 대안, 텍스트 프롬프트로 몇 분 안에 애니메이션·설명 영상 제작
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Turn any PNG into a South Park style talking avatar for live streaming. Upload
a picture, drag a line across it, and paste one link into OBS. The top half
hinges open when you talk.README 전문 보기 ↗Turn any PNG into a South Park style talking avatar for live streaming. Upload a picture, drag a line across it, and paste one link into OBS. The top half hinges open when you talk.
The avatar is drawn on a single canvas. The same PNG is drawn twice, each time clipped to one side of a straight split line, and the top piece is rotated around a hinge that sits on that line. Because the line can tilt, the two halves are polygons rather than rectangles: the line is clipped against the image rectangle with a Sutherland-Hodgman pass, which handles a line that leaves through the sides just as happily as one that leaves through the top.
The mouth interior is the wedge swept by the top piece's edge as it rotates - one circular sector either side of the hinge - masked by the artwork's own alpha so it can never spill outside the character's silhouette.
Audio is read straight from the browser with the Web Audio API, from one microphone chosen by the user. This is deliberately independent of OBS: OBS mixes game audio, music, alerts and voice chat, and none of that should move the mouth.
RMS level -> noise gate -> activity-scaled loudness span
-> attack/release smoothing -> quantise to N positions -> open angle
Two controls shape the feel:
The editor is one screen, not a wizard: the preview stays pinned on the left while the right-hand column walks through four numbered steps, one open at a time. Each step opens with a single plain-language sentence, shows two or three controls, and folds everything else into a "Fine-tune" disclosure - so the default view is a short list of decisions rather than a wall of sliders. Nothing is locked: any step can be reopened at any point, and saving works from any state.
Step three offers three presets - Calm, Chatty, Click-clack - which set motion mode, mouth positions, activity and the attack/release pair together, so nobody has to understand quantisation to get a good result.
The skin is a 1984 Macintosh read through an iOS lens: paper windows with
striped title bars and hard drop shadows on a dithered desk, holding
grouped list rows with hairline separators, generous touch targets and a
single accent colour. The bitmap display face (Silkscreen, self-hosted via
next/font) is used strictly for chrome - window titles, step numbers,
status labels. It has no lowercase, so it never renders user data: links,
ids, hex colours and measured values are all monospace.
There are two ways to drive a mouth from a microphone and they look nothing alike.
Following the envelope - opening as far as the voice is loud, and staying there while the sound continues - is what a VU meter does. It leaves the mouth hanging half open through every held syllable, which is the single thing that stops a rig reading as a cartoon.
Flapping is what the cartoon does. Each sound fires one complete
open-and-shut: the mouth is always either on its way open or on its way
shut, and it always reaches fully closed before the next flap begins. The
closing is the look, so flap is the default. hold keeps the old
envelope behaviour for anyone who wants it, and smooth is the same
without the steps.
Each flap also picks how far it opens, from the positions allowed by "how many mouth positions". Loudness decides which is most likely, but the opening the previous flap used is taken off the table entirely, so two flaps running never land on the same degree while any alternative exists.
Two things worth knowing fall out of loudness over time alone, with no need to recognise vowels, tones or words - which matters, because a rig with one degree of freedom has nowhere to put that detail anyway.
Speaking speed is counted as syllable onsets: the level dipping and rising again. Past about 4.5 a second the flapping shortens its cycle and the openings spread out, so a rush reads as a rush. Measured on synthetic speech, 3.6/s reads as normal and 8.4/s as fast, and the same loudness at a slower pace is correctly not a rush.
A shout is the level sitting well above the user's own gate for longer than any syllable could last - 280ms. The mouth then goes to its widest and stays there until the shout ends, rather than chattering through it. That it is measured against their gate rather than an absolute keeps it honest across microphones, and the duration requirement is what separates a shout from one loud word.
The two are independent, which is the useful part: a held shout produces one onset and then nothing, so it reads as loud and slow, while rapid speech reads as fast without being loud.
Silence does nothing at all. Below the gate the mouth is shut and the renderer draws the same frame every time - verified as pixel-identical output over three seconds, not merely as looking still. A word cut off halfway starts shutting immediately rather than finishing an opening nobody is making a sound for. Idle sway is the one thing that still moves in a pause, and it has its own switch.
| Motion | What it does |
|---|---|
| Left corner | Pivots at the left, so the right side lifts. |
| Right corner | Pivots at the right, so the left side lifts. |
| Straight up | Lifts with a slight lean, leaving an even gap. |
| Middle | Pivots in the centre: one side up, the other down. |
Two rules drive the choice, in src/lib/sequence.ts:
A corner almost never repeats; a straight lift happily can. A lift is the neutral move, so two in a row still reads as talking, whereas the same corner twice reads as a stuck hinge. The weights put corner repeats at under 2% and lift repeats near 10%, which keeps lifts the thing that breaks up a run rather than the other way about.
The mouth stays balanced. Every corner flap leans the jaw one way, and the next choice is weighted towards the other side; a lift lets the lean relax back. When a corner does repeat, the lift's weight is boosted for the next few flaps - measured, that lifts their share from 35% to 52% straight after a repeat, and it decays back.
A straight lift is never perfectly parallel. It takes a small lean of its own, against whichever way the jaw is currently sitting, so lifts vary without turning into another hinge.
The sequencer is pure, with its randomness injected, so the behaviour above is asserted over twenty thousand flaps rather than eyeballed: repeat rates, left/right skew under 1%, the post-repeat lift boost, and lean staying within range and averaging out.
Every motion is expressed as one rotation about a pivot followed by one translation, so the renderer has a single path for all of them. The mouth interior follows suit: a pure pivot sweeps its edge along an arc, so the gap is a circular sector either side of the hinge - two of them, which is what makes the middle pivot look right - while a motion that travels opens a quadrilateral between the resting edge and the moved one, which is exactly right for a straight lift.
Canvas padding is measured across every enabled motion at its worst case, including a lift at full lean, because the mouth may pick any of them mid-stream and a canvas sized for a pivot would crop a lift.
| Route | What it is |
|---|---|
/ | Landing page with a live example |
/edit | Upload a PNG and configure it |
/edit/[id] | The same editor, loaded from a saved config |
/live/[id] | Render only: no UI, no scrollbars, transparent background. This is the OBS Browser Source URL |
/how | Plain-language setup and troubleshooting |
npm install
npm run dev
Without a Blob store the app falls back to temporary local disk, which is fine for development and loses everything on restart.
Import the repository at vercel.com/new. Next.js is detected automatically and there is nothing to configure. Then two settings have to be dealt with by hand, and neither is where you would expect on a phone, where the dashboard collapses its side navigation.
1. Turn off Vercel Authentication. New projects enable it by default for
every *.vercel.app URL. It is the single worst default for this app,
because it fails invisibly: the page loads fine in your own browser, where
you are signed in to Vercel, and shows a login wall inside OBS, which is a
different browser with no session. You would go looking for a microphone
bug that was never there.
It lives on its own settings page, not under General:
/<team>/<project>/settings/deployment-protection
Set Vercel Authentication to Disabled. If your plan will not let you, note that protection never applies to custom domains, so attaching one and pointing OBS at that hostname works instead.
2. Give the project a public Blob store. Storage is on the account page, not inside the project, which is why it is not in the project's tabs:
/<team>/~/stores
Create a Blob store and choose Public access. Vercel recommends Private, but private blobs need a signed token on every read and OBS has no token, so the avatars would never load. Public is correct here, and it is the tradeoff the app is built around: ids are unguessable, but anyone holding a link can view it. Access mode cannot be changed after creation.
Connecting a store to a project only sets one variable. If the Connect
Project control is not visible — it collapses out of the mobile layout —
set it yourself from the store's Quickstart panel, .env.local tab:
BLOB_READ_WRITE_TOKEN=vercel_blob_rw_...
Add that under the project's Settings → Environment Variables for all
environments. Importing the repo may also have auto-created a store and set
this variable already, since Vercel detects @vercel/blob in the manifest —
check before creating a second one.
3. Redeploy. Environment variables do not reach a deployment that already exists. Pushing a commit also works, and is easier from a phone than finding the redeploy menu.
Until the token is in place, both write routes return a 503 naming the fix
rather than pretending to save; the editor shows it in place. Uploaded PNGs
land in avatars/<id>.png and configs in configs/<id>.json. There is no
database, no auth and no accounts: the id in the URL is the only key, which
is why the app tells people to bookmark their editor link.
Avatars are deleted a week after they were last saved. vercel.json
schedules a daily sweep of /api/cleanup, which groups every object in the
store by its id and removes the pair - picture and settings together - when
the newest of the two is past the window. Saving from the editor counts as
touching it, so one that is actively used keeps renewing itself, and an old
picture whose settings were edited yesterday is never half-deleted into a
broken link.
This is a deliberate product decision rather than a storage saving. People
upload their own faces to try a toy; those files should not sit on someone
else's server forever. The success panel names the date, and /how
explains how to renew.
The window is RETENTION_DAYS in src/lib/retention.ts. It is a plain
constant rather than an environment variable so the number the interface
promises and the number the sweep enforces cannot drift apart.
The sweep endpoint is safe to call by anyone: it can only remove what is
already expired, so an unexpected caller does exactly what the timer would
have done. Setting CRON_SECRET on the project enforces a bearer token as
well, and Vercel sends it automatically on scheduled runs.
| Script | Purpose |
|---|---|
npm run dev | Development server |
npm run build | Production build (also typechecks) |
npm run typecheck | Types only |
OBS Browser Sources run inside CEF, which cannot show a permission prompt.
Most setups grant microphone access automatically; if yours does not, the
avatar will show a message rather than freezing silently, and /how explains
the two ways around it. Never diagnose a still avatar by guessing - open
/live/<id> in a normal browser first to see which half is at fault.