Repository navigation
Releases: vannt-dev/nimbleclip
Release list
NimbleClip 1.13.2
- A TikTok photo post saved as a video has its music again, and the post's
MP3 audio downloads again. Both had stopped receiving the track: the video
came out silent and the audio did not arrive.
What's Changed
- CI: shorter Android jobs, and a release that does not repeat CI's checks by @vannt-dev in #52
- Health check: a site refusing GitHub's network is not a broken extractor by @vannt-dev in #53
- Health check: the long-video stream check is refused from GitHub too by @vannt-dev in #55
- fix: 1.13.2, a TikTok photo post saved as a video has its music again by @vannt-dev in #56
Full Changelog: v1.13.1...v1.13.2
NimbleClip 1.13.1
- A paused YouTube audio download stays paused when the app is closed and
opened again, and keeps what had arrived. It used to carry on by itself at
the next launch. Its card also shows how much is kept, where it read 0 B. - On Android 7.0, YouTube qualities above 360p are no longer offered. That
system cannot join their picture and sound, so such a download fetched
everything and then failed. 360p and audio download as before; Android 7.1
and later are unchanged.
What's Changed
- fix: keep a paused download paused across a launch, and offer Android 7.0 only what it can join by @vannt-dev in #50
- chore(release): 1.13.1 by @vannt-dev in #51
Full Changelog: v1.13.0...v1.13.1
NimbleClip 1.13.0
- YouTube audio downloads are much faster: a five-minute song arrives in a
few seconds where it took two and a half minutes, a four-hour recording in
under a minute. Pause keeps what has arrived, and a download cut off by the
app closing is finished the next time it opens. Tried on Android; iOS runs
the same code and has not been tried on a device. - Downloads are finished while the app is in the background, on Android.
The transfers themselves always carried on; what followed them did not
when Android froze or ended the app: joining the parts of an HD video,
converting audio to MP3, a stream fetched segment by segment, a slideshow.
While any download is running NimbleClip now shows a notification
("NimbleClip is downloading") and the system leaves it working. The
notification goes a few seconds after the last
download ends. Swiping the app away still stops it. - The repository builds without the private core.
dart run tool/use_public_core.dartputs a public core in its place
(lib/services/extractors_public): one extractor for links to media files
and for pages with Open Graph metadata, and stand-ins for the rest. Android,
iOS and Web build from a plain clone that way; the sites NimbleClip knows by
name still need the full core, which the released builds are made with. - The platforms are shown by their own marks (YouTube, TikTok, Facebook, X,
Instagram, Threads, Pinterest, SoundCloud, Flickr) on the home screen, on
the labels of a result and on the cards of the Downloads screen, where
stand-in pictures were used before. The marks come from Font Awesome's free
brand set; its licence is on the Open-source licences page.
What's Changed
- feat(ui): show each platform by its own mark by @vannt-dev in #46
- feat: build without the private core, with a public one in its place by @vannt-dev in #48
- feat: faster YouTube audio downloads, and downloads finished in the background by @vannt-dev in #47
- chore(release): 1.13.0 by @vannt-dev in #49
Full Changelog: v1.12.0...v1.13.0
NimbleClip 1.12.0
-
YouTube videos longer than about a minute download again above 360p, and
so does their audio. Such a download had started to stop part-way and end
in "Download failed". -
Three more sources: Pinterest (a pin's video or picture,
pin.itshort
links included), SoundCloud (a track, as the MP3 SoundCloud serves) and
Flickr (a photo at its largest size, or a video's files,flic.krshort
links included). A SoundCloud track that only offers a preview and a Flickr
photo whose owner turned downloads off are refused with a message that says
so. -
A Save audio as MP3 switch in Settings, on Android. With it on, an audio
download that arrives in another format (YouTube's M4A, for one) is
converted to MP3 on the device when it finishes: 128, 192 or 256 kbps,
following the source's own bitrate. The Downloads screen shows the
conversion as progress and it can be cancelled; if it cannot be done, the
file is kept as it was fetched and its card says so. Downloads that finish
while the app is closed are not converted. A converted download is listed
as MP3 audio. The encoder is LAME 3.100
(LGPL), built from source into its own library; see
android/app/src/main/cpp/README.md. -
Settings → About has an Open-source licences entry. It opens the licence page, which
lists the packages the app is built from and the licence of LAME, the MP3 encoder (LGPL):
that text has to travel with the app, not only with its source. -
More of the app now lives in the private core (the submodule under
lib/services/extractors): the HLS and DASH stream code, the Android
encoders (slideshow, stream join, segment cipher, MP3) and the extractor
tests with their fixtures. Nothing changes in the app itself. -
A finished download that carries a note, such as a slideshow rendered
without its music, now shows it on its card. -
The supported platforms on the home screen are shown as a single row of
icons. A platform's name is still there as its tooltip, for screen readers
and in the message a tap shows.
What's Changed
- feat(downloads): save audio as MP3 with a bundled LAME encoder by @vannt-dev in #40
- chore: move the stream code, the encoders and the extractor tests into the private core by @vannt-dev in #41
- feat(settings): show the open-source licences, including the MP3 encoder's by @vannt-dev in #42
- feat: add Pinterest, SoundCloud and Flickr as sources by @vannt-dev in #43
- feat(home): show the supported platforms as icons only by @vannt-dev in #44
- chore(release): 1.12.0 by @vannt-dev in #45
Full Changelog: v1.11.0...v1.12.0
NimbleClip 1.11.0
-
Preview plays a YouTube video again. On Android the default quality above
360p is joined on the device from separate picture and sound streams, which
left Preview with "No video source is available"; it now plays the same
video at the quality that comes whole. -
Downloaded files are named after the platform and a short id only
(tiktok_a474a6364e1b.mp4). The author and the start of the caption are no
longer in the name: a caption in decorated letters made names that were
long and hard to read. -
A Download on Wi-Fi only switch in Settings. While it is on and the
device is on mobile data or offline, new downloads wait in the queue and
start by themselves when Wi-Fi or a cable is back; the Downloads screen says
how many are waiting. On Android and iOS the system also pauses a file
transfer that is already running and resumes it later. A stream being
fetched segment by segment (HLS, DASH) or a slideshow being rendered is not
interrupted once it has started. -
A link to a YouTube playlist (
youtube.com/playlist?list=…, also from
YouTube Music) is replaced by its videos, which are analyzed and queued like
any other batch. Up to 20 are taken, the size of a batch, in the playlist's
order; a longer playlist says that the rest were left out. A private,
removed or empty playlist says so. A video link that only carries a
list=parameter is still treated as that one video.
What's Changed
- feat(youtube): analyze the videos of a playlist link as a batch by @vannt-dev in #36
- feat(downloads): hold downloads until Wi-Fi with a Wi-Fi only setting by @vannt-dev in #37
- chore: keep the extractors in a private submodule and obfuscate release builds by @vannt-dev in #38
- chore(release): 1.11.0 by @vannt-dev in #39
Full Changelog: v1.10.0...v1.11.0
NimbleClip 1.10.0
- On Android, a video served as a DASH stream can be downloaded: a link to an
.mpdmanifest, or a page whose player names one. Each size is offered
once, its segments and those of the sound are fetched and joined into one
MP4, and Preview plays the stream. A broadcast still going on, content under
a key system, and a manifest cut into several periods say what they are. - An HLS stream encrypted with a key its playlist names (
AES-128) is now
decrypted and downloaded like any other. Sample encryption and the key
systems of a DRM are still refused as protected. - A stream address found in a page's script keeps the part of its query that
was written with an escaped ampersand; it was being cut off there, which
broke signed addresses. - Scratch files an interrupted download left in the cache - the segments of a
stream, the images of a slideshow - are cleared the next time the app
starts, instead of staying until the cache is emptied by hand.
What's Changed
- feat: DASH streams, HLS with a playlist key, and scratch cleanup by @vannt-dev in #34
- chore(release): 1.10.0 by @vannt-dev in #35
Full Changelog: v1.9.0...v1.10.0
NimbleClip 1.9.0
- Threads links are supported: a public post's video, pictures, or a carousel
mixing the two, fromthreads.comandthreads.net, including the short
/t/<code>form. A text-only, private or deleted post says that it has no
picture or video. - Links to other sites find more:
<video>and<audio>elements, JSON-LD
media (VideoObject,AudioObject,ImageObject),og:audio, and every
og:imageof a gallery page as its own picture. Several videos on one page
are offered as separate downloads; the encodings of one<video>element
count as one clip, MP4 preferred. - On Android, a video served as an HLS stream can be downloaded: a link to an
.m3u8playlist, or a page whose player names one, even in a script. Each
size the stream comes in is offered once, its segments are fetched and
joined into one MP4, and Preview plays the stream. A live broadcast and an
encrypted stream say what they are. Elsewhere, and for DASH, a page that
only plays a stream now says so instead of "no video was found". - A Threads post with no media of its own offers that of the post it quotes or
reposts, and a video carried inline from Instagram. - A downloaded picture is named after its place in the post ("Image 3") in the
download list, where it used to read "Instance of 'ImageIndex'". Entries
already in the list are put right when it is read. - Saved files carry the author and the start of the title:
threads_nasa_LIFTOFF_<id>.mp4where it wasthreads_<id>.mp4. - A Facebook story, which Facebook shows only to a logged-in reader, is
fetched through an external service when Facebook itself shows no video.
Like the other external services, this follows the setting that allows
them. - Instagram reels, stories and highlights work again on networks that cannot
reach the service they are read through: a second service is asked when
the first does not answer. - An Instagram video read through the service is the video, not its
thumbnail. The thumbnail was being offered as the Reel, which then would
not play and saved as a picture named.mp4. - A Facebook album is whole again. The service its photos are read through
moved its address and answered the old one with a redirect, so every album
had shrunk to its cover photo; the redirect is now followed. - The home screen shows every supported platform at once instead of a row that
ran off the edge, and asks for "a link" rather than "a video link".
What's Changed
- feat: download from Threads, and find more media on other pages by @vannt-dev in #31
- feat: HLS streams, Facebook stories, and Instagram fixes by @vannt-dev in #32
- chore(release): 1.9.0 by @vannt-dev in #33
Full Changelog: v1.8.0...v1.9.0
NimbleClip 1.8.0
- On Android, a 480p-1080p YouTube download now keeps going after the app is
closed or Android ends it. Both streams are queued up front as
system-managed downloads, in parts, several of which run at once. One
notification counts the parts. Joining the streams still needs the app: if
the parts finish while it is closed, the video is joined the next time it
opens. - When YouTube refuses the page even after the YouTube library's own five
retries, the app now says YouTube is refusing requests for now and to try
again in a few minutes. It used to report "no downloadable stream", which
blamed the video. - Starting the same merged YouTube download or TikTok slideshow while it is
still running no longer produces it twice. Downloads fetched from a URL were
already guarded; options produced on the device were split off before that
check. - X, Instagram and Facebook failures now keep every strategy's own cause in
the copied diagnostics, as YouTube's do since 1.7.0. Offline, each of them
used to report only that the post had no media. - The live extractor check now covers a YouTube Short shared with
?si=.
What's Changed
- fix: report real extraction causes and refuse duplicate rendered downloads by @vannt-dev in #26
- feat(downloads): keep an HD merge fetching after the app process ends by @vannt-dev in #27
- chore(release): 1.8.0 by @vannt-dev in #28
- test(downloads): wait for the receipt, not just the finished status by @vannt-dev in #29
Full Changelog: v1.7.0...v1.8.0
NimbleClip 1.7.0
- Added 480p, 720p and 1080p YouTube downloads on Android. YouTube serves
nothing above 360p with sound; higher qualities are a video-only stream plus
a separate audio stream. Both are now fetched and joined on the device into
one MP4 by copying their samples, without re-encoding, so a 1080p clip takes
seconds to join and the picture is exactly what YouTube sent. H.264 only,
which is why the ceiling is 1080p: above it YouTube offers only VP9 and AV1.
Other platforms keep the 360p option and see no higher row. - Each stream is fetched in parts and written straight to disk: a 3-minute
1080p video (84 MB) now arrives in under a minute on an emulator. - A vertical Short labelled 720p is 720x1280. Qualities are compared on the
short side, as YouTube names them, so a Short is not mistaken for 1280p and
dropped by the 1080p ceiling. - A retry of a failed merged download re-reads the video first: the stream
URLs are signed and expire within hours. - Fixed YouTube Shorts share links (
/shorts/<id>?si=...) failing with "no
streams". The YouTube library's own Shorts pattern requires the ID to end
the URL, so it rejected every copied share link; the extractor now hands it
the parsed ID. - The YouTube audio option now picks the best AAC stream. It used to pick the
highest bitrate overall, usually Opus in WebM, and saved it under an.m4a
name it is not. - When a YouTube extraction fails, copied diagnostics now include the native
client's own error. It used to be discarded in favour of the fallback's
failure, which is how the Shorts bug above surfaced as "no streams". - Fixed Facebook albums arriving as their cover photo alone. The gallery
service moved to itswwwhost and answers the bare domain with a308
redirect, which is not followed for a POST, so every gallery lookup failed
from 2026-09-16. - Upgraded
cached_network_imageto 4.0.2 and refreshed other dependencies
within their existing constraints. The iOS build now needs Xcode 26.1.1 or
later, sinceconnectivity_plus(viabackground_downloader) uses iOS 26
APIs.
What's Changed
- docs: add download badges to README by @vannt-dev in #22
- fix: restore the Facebook gallery fallback and the live slideshow check by @vannt-dev in #23
- feat(youtube): 1080p downloads on Android, Shorts share links, AAC audio by @vannt-dev in #24
- chore(release): 1.7.0 by @vannt-dev in #25
Full Changelog: v1.6.0...v1.7.0
NimbleClip 1.6.0
- Added a slideshow option to TikTok photo posts on Android: the post's images
and its music are rendered on the device into one 1080x1920 MP4, three
seconds an image, instead of arriving as a folder of pictures and a separate
audio file. The option carries no download URL — there is nothing to fetch —
so it is split off ahead of the download queue and rendered instead, and the
finished file enters history as a file that already exists. - The music is transcoded to AAC before a single frame is muxed, because
MediaMuxerrefuses both MP3 in an MP4 and any track added after the file
has been started. A track that will not decode therefore cannot damage the
picture: the render carries on and produces a silent video with a note on it,
since a slideshow without music is usable and a failed one is not. - The option is offered only where it can actually run. The renderer's own
runtime check is what decides — a Dart conditional import cannot tell Android
from iOS, since both havedart.library.io— so iOS, desktop and Web see no
slideshow row at all rather than one that fails when tapped. - A slideshow render now reports its progress and can be cancelled. The encode
runs outside the download queue, so neither the progress bar nor the Cancel
button reached it: a render showed nothing for its whole duration and then
jumped to done, and cancelling appeared to work before the finished encode
overwrote the row back to completed. The encoder reports once per image and
checks for a cancellation between images, so a tap stops it within one image
and leaves no half-written file behind. - Fixed a slideshow retried after the app restarted being fetched instead of
re-rendered. The source a render was built from is held in memory while a
failed task is written to history, so on the next launch Retry fell through
to the download path with an empty URL. The retry now re-extracts the post to
recover the source. - Upgraded
chewieandvideo_player_androidto their latest patch releases.
What's Changed
- feat: render TikTok photo posts into a video, and release 1.6.0 by @vannt-dev in #20
- test(images): measure the thumbnail decode without imageBuilder by @vannt-dev in #21
Full Changelog: v1.5.2...v1.6.0