{"id":20529774,"url":"https://github.com/wofwca/jumpcutter","last_synced_at":"2025-05-16T04:03:39.505Z","repository":{"id":38080242,"uuid":"234912300","full_name":"WofWca/jumpcutter","owner":"WofWca","description":"⏩ Fast-forwards long pauses between sentences — watch lectures ~1.5x faster (browser extension)","archived":false,"fork":false,"pushed_at":"2025-04-04T21:59:08.000Z","size":6633,"stargazers_count":394,"open_issues_count":120,"forks_count":17,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-16T04:03:15.821Z","etag":null,"topics":["agpl","audio","audio-processing","browser-extension","chrome-extension","firefox-addon","firefox-extension","productivity","video","web-audio-api","webextension","youtube"],"latest_commit_sha":null,"homepage":"https://chrome.google.com/webstore/detail/jump-cutter/lmppdpldfpfdlipofacekcfleacbbncp","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WofWca.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"COPYING","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"WofWca","custom":["https://antiwarcommittee.info/en/sunrise/#help","https://github.com/WofWca/jumpcutter#donate"]}},"created_at":"2020-01-19T14:21:13.000Z","updated_at":"2025-05-12T10:04:47.000Z","dependencies_parsed_at":"2023-02-17T03:31:03.601Z","dependency_job_id":"b0bf5641-0eb5-4247-94c1-d583cc9a5885","html_url":"https://github.com/WofWca/jumpcutter","commit_stats":{"total_commits":1214,"total_committers":10,"mean_commits":121.4,"dds":"0.17133443163097195","last_synced_commit":"7431f9028d0649e1eb37435b0567c809107b3966"},"previous_names":[],"tags_count":85,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WofWca%2Fjumpcutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WofWca%2Fjumpcutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WofWca%2Fjumpcutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WofWca%2Fjumpcutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WofWca","download_url":"https://codeload.github.com/WofWca/jumpcutter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254464891,"owners_count":22075570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agpl","audio","audio-processing","browser-extension","chrome-extension","firefox-addon","firefox-extension","productivity","video","web-audio-api","webextension","youtube"],"created_at":"2024-11-15T23:34:03.320Z","updated_at":"2025-05-16T04:03:39.485Z","avatar_url":"https://github.com/WofWca.png","language":"TypeScript","funding_links":["https://github.com/sponsors/WofWca","https://antiwarcommittee.info/en/sunrise/#help","https://github.com/WofWca/jumpcutter#donate","https://liberapay.com/WofWca"],"categories":[],"sub_categories":[],"readme":"# \u003cimg src=\"./src/icons/icon.svg\" alt=\"Logo\" height=\"32\"/\u003e Jump Cutter\n\n[![Chrome Web Store](https://img.shields.io/chrome-web-store/users/lmppdpldfpfdlipofacekcfleacbbncp?logo=google-chrome)][chrome-web-store]\n[![Firefox Browser Add-ons](https://img.shields.io/amo/users/jump-cutter?logo=firefox-browser)][addons-mozilla-org] \u003c!-- [![Liberapay](https://img.shields.io/liberapay/receives/WofWca?logo=liberapay)](https://liberapay.com/WofWca) --\u003e [![Matrix](https://img.shields.io/matrix/jump-cutter-extension:matrix.org?logo=matrix\u0026server_fqdn=matrix.org)](https://matrix.to/#/#jump-cutter-extension:matrix.org)\n[![Discord](https://img.shields.io/discord/678444692592918548?logo=discord)](https://discord.gg/HCjghyT)\n[![Translation status](https://hosted.weblate.org/widgets/jump-cutter/-/svg-badge.svg)][weblate]\n\nDownload:\n\n[![Chrome Web Store](docs/extension-store-badges/chrome.png)][chrome-web-store]\n[![Firefox Browser Add-ons](docs/extension-store-badges/mozilla.svg)][addons-mozilla-org]\n[![Microsoft Edge Add-ons](docs/extension-store-badges/microsoft.svg)][microsoft-edge-addons]\nor from GitHub: [Chromium](https://github.com/WofWca/jumpcutter/releases/latest/download/lmppdpldfpfdlipofacekcfleacbbncp_main.crx\n) / [Gecko (Firefox)](https://github.com/WofWca/jumpcutter/releases/latest/download/jump_cutter.xpi)\n\nSkips silent parts in videos, in real time.\n\nCan be useful for watching lectures, stream recordings (VODs), webinars, podcasts, and other unedited videos.\n\nDemo:\n\n\u003c!-- TODO refactor: put the file in the repo so it's set in stone? --\u003e\n\u003c!-- The source video:\nhttps://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-034-artificial-intelligence-fall-2010/lecture-videos/lecture-16-learning-support-vector-machines/\n(or https://youtu.be/_PwhiWxHK8o).\nThis video's license: CC BY-NC-SA 4.0 (https://creativecommons.org/licenses/by-nc-sa/4.0/).\nNot sure if I did comply with the license here.\nBut I believe this use case would be considered \"fair use\" anyway.\n --\u003e\n\u003chttps://user-images.githubusercontent.com/39462442/131825020-5308b879-0509-41a3-95c9-bb4ad8938dc0.mp4\u003e\n\nInspired by [this video](https://youtu.be/DQ8orIurGxw) by carykh.\n\n## How it works\n\nSimple (mostly).\n\n\u003c!--\nIdk where to put this part. It seems out of place as an introduction,\nbecause we don't really have to say anything about looking ahead\nto explain the simpler case, when \"margin before\" is 0.\nAnd both algorithms have their own pros and cons even with\n\"margin before\" being 0.\n\nWith the current state of the web APIs,\nthere is no direct way to inspect audio samples of a media file/stream\nanywhere other than at the current playback position of the media element.\nOtherwise it would be pretty easy to employ the algorithms used in\nthe [analogous software](https://alternativeto.net/software/jump-cutter/),\nsuch as\n\n* [jump-cutter](https://github.com/jfkthame/jump-cutter)\n* \u003chttps://github.com/carykh/jumpcutter\u003e\n* ExoPlayer ([SilenceSkippingAudioProcessor](https://github.com/google/ExoPlayer/blob/9c9f5a0599ec012d5cc46e3bd2e732a589adf61d/library/core/src/main/java/com/google/android/exoplayer2/audio/SilenceSkippingAudioProcessor.java))\n* ffmpeg ([`silenceremove`](https://ffmpeg.org/ffmpeg-filters.html#toc-silenceremove))\n\nSo we have to work around that fact. --\u003e\n\nCurrently there are 2 separate algorithms in place.\n\nThe first one we call \"the stretching algorithm\", and it's in [this file](./src/entry-points/content/ElementPlaybackControllerStretching/ElementPlaybackControllerStretching.ts). It simply looks at the output audio of a media element, determines its current loudness and, when it's not loud, increases its `playbackRate`. (We're using Web Audio API's\n[`createMediaElementSource`](./src/entry-points/content/ElementPlaybackControllerStretching/ElementPlaybackControllerStretching.ts#L299)\nand [`AudioWorkletProcessor`](./src/entry-points/content/SilenceDetector/SilenceDetectorProcessor.ts)\nfor this).\n\n\u003cdetails\u003e\u003csummary\u003eDetails, why it's called \"stretching\"\u003c/summary\u003e\nThe algorithm we just described cannot \"look ahead\" in the audio timeline.\nIt only looks at the current loudness, at the sample that we've already sent\nto the audio output device.\n\nBut looking ahead (a.k.a. \"Margin before\") is important, because, for example,\nthere are certain sounds in speech that you can start a word with\nthat are not very loud.\nBut it's not good to skip such sounds just because of that.\nThe speech would become harder to understand.\nFor example, \"throb\" would become \"rob\".\n\u003c!-- You'd probably still understand what's being said based on the context,\nbut you'd need to use more mental effort. --\u003e\n\nHere is where the \"stretching\" part comes in.\nIt's about how we're able to \"look ahead\" and slow down\nshortly before a loud part.\nBasically it involves slightly (~200ms) _delaying_ the audio\nbefore outputting it (and that is for a purpose!).\n\nImagine that we're currently playing a silent part,\nso the playback rate is higher.\nNow, when we encounter a loud part, we go\n\"aha! That might be a word, and it might start with 'th'\".\n\u003c!-- , which we might not have marked as loud, because 'th' is not that loud\" --\u003e\nAs said above, we always delay (buffer) the audio for ~200ms\nbefore outputting it.\nSo we know that these 200ms of buffered audio\nmust contain that \"th\" sound,\nand we want the user to hear that \"th\" sound.\nBut remember: at the time we recorded the said sound,\nthe video was playing at _a high speed_,\nbut we want to play back that 'th' _at normal speed_.\nSo we can't just output it as is. What do we do?\n\nWhat we do is we take that buffered (delayed) audio,\nand we _slow it down_ (stretch and pitch-shift it)\nso that it appears to have been played at normal speed!\nOnly then do we pass it to the system (which then passes it to your speakers).\n\nAnd that, kids, is why we call it \"the stretching algorithm\".\n\nFor more details, you can check out the comments in its source code.\n\u003c/details\u003e\n\nThe second algorithm is \"the cloning algorithm\", and it's [here](./src/entry-points/content/ElementPlaybackControllerCloning/ElementPlaybackControllerCloning.ts). It creates a hidden clone of the target media element and plays it ahead of the original element, looking for silent parts and writing down where they are. When the target element reaches a silent part,\nwe increase its `playbackRate`, or skip (seek) the silent part entirely.\nCurrently you can enable this algorithm by checking the \"Use the experimental algorithm\" checkbox.\n\n\u003c!-- Referenced lines and lines might get shifted.\nNeed to reference specific commits perhaps,\nbut I don't want to link to GitHub. --\u003e\nWe look for video elements by\n[injecting a script in all pages](./src/manifest_base.json#L16-L23)\nand simply\n[`document.getElementsByTagName('video')`](./src/entry-points/content/watchAllElements.ts#L37).\nBut new video elements could get inserted\n_after_ the page has already loaded,\nso we [watch for new elements with a `MutationObserver`](./src/entry-points/content/watchAllElements.ts#L90).\n\n\u003cdetails\u003e\u003csummary\u003eHigh-level architecture chart\u003c/summary\u003e\n\nIf below you see a block of text instead of a chart,\ngo [here](https://mermaid.ink/img/pako:eNrNWG1vm0gQ_isrTqlaKTEs7_jDSVES6Sr1JapzinT16bosszYNsGhZmqZx_nsXsI3BsbGvul5tOYFhdmb2mZmHgUeN8gi0sTYTJJ9Ps5OT-gDdXE6zaYbU5-QE3by_fI9IFKEkzu4KNJcyL8a6noJISRyNPhcjLmZ68ZBJ8lVnCb-ncyLkaC7T5Lc4kyAIlTHPVhbviaTz8yS5SiCFTBYfp1pf1ChWn4Rz5ZJxgVKIYoJgS4NnSM4B5WQGU-3vRk6TmN5tOUJTbRX7LJbzMhxRnuq3nN1Son8u05yWUkWrhwkPdT8wiBmaTmD7zAoYdhyLhgFhoeFSm1Js0CAyCQ70QlBdWRcPZzlXuy10ytWeM6n33Y9U1NoKBCV_W21odfFCLRI8SUAoOHZfbLdd7ZkLOodCCiK5OO1tfreNo2CwbUaiEAe-yULwosg0qGt7NiYQgOfYIQlMFxu2uRuG3YF0ANlK1tnZ74upxrN3cN9Z_3I0Gq2q4NVUW6AhtPYgUfngIp7FGUnQHzdv32wqLhCdc15Aq__YCNokkDwXPBcxkRtCutZ_WiakZ2bI7fLgOiEPIaF37cKLhGdxNkMvdqtMpAAFpNKaZhstPGRyQ7Uow4YDptrgqnX2hjQ_HmCsD2CB8qXuhw6-nC2LvwGwvdBHstcRg7Ae0xcWYwbGFvYjqkjBNjwgLGCKGPzIsiJG1NcIHQt298VQOIMKnfZ5o3iSzIFECun1cQtNhWSBKjM1dlRZgBWXbnAKr_m2ptsiTiCjgATJZlD0oFx7OAqzwPeBWgYOmQkuVZC5lFqmzzyL2NjzmOcYNsOAfwCzdWAdcAYzrxoSLdDOlkQCGIgKjgXqgdsiUdvoorY4uO-oAFXjlRCWS24VnBOSwkTQxvRWUHUShwI6aE97vW_mfX-Yx9QCBBFhDJtm9XMt4hgsxNQm2AA7xBb1WIQDg7IfqIW9wXbqo0ayBmfCS0GhGkk-bQnbPqmHGgq5ukuRJEHPK5EsQnOeREqncbCbqD712mvL9VHQOiFlClzHMlyXOoTazHVtMPwgDLCLsU8YWB6BPbfsLf96Eof7Eavvaf-mRBczkBuGNtO1QM_koDExafrsEiRQNfxglbCeqEW7lHESf1Mh3kKIzsso5uj8-nWH9aJ60Yrzetno-zquzhXBWY5hEFDtFgQ28UNwwlCVd1QRn-GDHzjM3lPnPff982vBFS4FX01Tz3BAw_ZbySEVFIut7T0PcGOpBW3y-s3Vu4urf67eXaIX2-LJzfmHGwRfuqP6vYILyThVMytJ8-WFTnmspxDIlsUyPMJ0R54jppiNhcO3ilb542Em_7dxpo3hV5lo2ogO0ekQTa8OzZ_Y6Oav3-iH1MDAGPA8C5jPo_9fssBx_V3zw-Y7inqYVage8dBz2HNUs2e5sr__ebPxfc3zMleVWv9vN_7yz9enqH438qpXebXiT3ouzytf-nmej4ovkCgm0g55TO4gUIernWrLN0DaWHusbEw1RWSpMjhWhxEwUiaysv6kVEkp-eQho9pYihJONcHL2VwbM5IU6qzMI8WJlzFRnJ2uVHKS_cV5ulZS59r4Ufuqjc-cAI8C9cf1bN-wXd8_1R4qsWMqsWl6hmN4Pjadp1PtW20Cj3wHO2r4MbFl2b5tPX0HOWuO6Q?type=png).\n\n```mermaid\ngraph\n%%graph TD\n\n    %% TODO add links https://mermaid.js.org/syntax/flowchart.html#interaction\n\n    watchAllElements[\"watchAllElements\n        looks for media elements\n        on the page\"]\n    click watchAllElements \"https://github.com/WofWca/jumpcutter/blob/890a2b25948f39f1553cb9afb06c4cc10c9d2a19/src/entry-points/content/watchAllElements.ts\"\n\n    AllMediaElementsController[\"AllMediaElementsController\n        the orchestrator,\"]\n    click AllMediaElementsController \"https://github.com/WofWca/jumpcutter/blob/44fadb1982fbe7dd20c64741ae9e754ba9261042/src/entry-points/content/AllMediaElementsController.ts\"\n\n    watchAllElements --\u003e|\"onNewMediaElements(...elements)\"| AllMediaElementsController\n    AllMediaElementsController --\u003e|original HTMLMediaElement| chooseController{choose\n        appropriate\n        controller}\n    chooseController --\u003e|original HTMLMediaElement| ElementPlaybackControllerCloning \u0026 ElementPlaybackControllerStretching\n\n\n    %% ElementPlaybackControllerCloning\n\n    %% subgraph \"ElementPlaybackControllerCloning\"\n\n    ElementPlaybackControllerCloning[\"ElementPlaybackControllerCloning\n        controls playbackRate\n        of the original\n        HTMLMediaElement\"]\n    click ElementPlaybackControllerCloning \"https://github.com/WofWca/jumpcutter/blob/3ff011318dc9af407eaf9f4cc8d33dfafaf0b53e/src/entry-points/content/ElementPlaybackControllerCloning/ElementPlaybackControllerCloning.ts\"\n\n    Lookahead[\"Lookahead\n        plays back the clone element\n        to look for silence ranges\"]\n    click Lookahead \"https://github.com/WofWca/jumpcutter/blob/988ec301bf2e6c07e6cc328f73a4177f7504f1e1/src/entry-points/content/ElementPlaybackControllerCloning/Lookahead.ts\"\n\n    ElementPlaybackControllerCloning --\u003e | original HTMLMediaElement reference| Lookahead\n    Lookahead --\u003e |silence ranges| ElementPlaybackControllerCloning\n\n    createCloneElementWithSameSrc --\u003e |HTMLMediaElement clone| Lookahead\n    Lookahead --\u003e |original HTMLMediaElement reference| createCloneElementWithSameSrc\n    click createCloneElementWithSameSrc \"https://github.com/WofWca/jumpcutter/blob/e9daff122f12263a50fb1c4a10e4b13c7fd190cf/src/entry-points/content/ElementPlaybackControllerCloning/createCloneElementWithSameSrc.ts\"\n\n    cloneMediaSources[\"`cloneMediaSources\n        intercepts all MediaSources\n        and holds a clone\n        HTMLMediaElement`\"]\n    click cloneMediaSources \"https://github.com/WofWca/jumpcutter/blob/5bcfdaf53066c5ac4f664e089b916118afe37ae2/src/entry-points/content/cloneMediaSources/lib.ts\"\n\n    cloneMediaSources --\u003e|HTMLMediaElement clone| Lookahead\n    Lookahead --\u003e|getMediaSourceCloneElement| cloneMediaSources\n\n    SilenceDetector1[\"SilenceDetector\n        utilizes Web Audio API\n        to detect silence\"]\n    click SilenceDetector1 \"https://github.com/WofWca/jumpcutter/blob/e3283500aeefe994a8be5bb7fdd8f7308e895f4f/src/entry-points/content/SilenceDetector/SilenceDetectorProcessor.ts\"\n    Lookahead --\u003e |clone HTMLMediaElement audio| SilenceDetector1\n    SilenceDetector1 --\u003e |\n        SILENCE_END \u0026\n        SILENCE_START events\n        with timestamps\n    | Lookahead\n\n    %% end\n    \n    %% ElementPlaybackControllerStretching\n\n    %% subgraph \"ElementPlaybackControllerStretching\"\n\n    ElementPlaybackControllerStretching[\"ElementPlaybackControllerStretching\n        controls playbackRate\n        of the original\n        HTMLMediaElement\"]\n    click ElementPlaybackControllerStretching \"https://github.com/WofWca/jumpcutter/blob/3ff011318dc9af407eaf9f4cc8d33dfafaf0b53e/src/entry-points/content/ElementPlaybackControllerStretching/ElementPlaybackControllerStretching.ts\"\n\n    SilenceDetector2[\"SilenceDetector\n        utilizes Web Audio API\n        to detect silence\"]\n    click SilenceDetector2 \"https://github.com/WofWca/jumpcutter/blob/e3283500aeefe994a8be5bb7fdd8f7308e895f4f/src/entry-points/content/SilenceDetector/SilenceDetectorProcessor.ts\"\n    ElementPlaybackControllerStretching --\u003e |original HTMLMediaElement audio| SilenceDetector2\n    SilenceDetector2 --\u003e |\n        SILENCE_END \u0026\n        SILENCE_START events\n        with timestamps\n    | ElementPlaybackControllerStretching\n\n    %% end\n\n\n    %% Telemetry\n\n    %% ElementPlaybackControllerCloning \u0026 ElementPlaybackControllerStretching --\u003e |telemetry| AllMediaElementsController\n\n    Popup[\"Popup\n        (UI, chart)\"]\n    click Popup \"https://github.com/WofWca/jumpcutter/blob/44fadb1982fbe7dd20c64741ae9e754ba9261042/src/entry-points/popup/App.svelte\"\n    AllMediaElementsController --\u003e |telemetry| Popup\n```\n\n\u003c/details\u003e\n\n\u003c!-- FYI this section is linked from CONTRIBUTING.md --\u003e\n## Contribute\n\n* [🌐 Translate (on Weblate)][weblate]\n* 👨‍💻 Code. See [CONTRIBUTING.md](./CONTRIBUTING.md) on how to get started. And feel free to contact me.\n* [💸 Donate](#donate)\n* General feedback and questioning my decisions is appreciated\n\n\u003c!-- FYI this section is linked from CONTRIBUTING.md --\u003e\n## Build\n\n1. Install base tools:\n    * [Node.js](https://nodejs.org/).\n    * [Yarn v1](https://classic.yarnpkg.com/docs/install).\n2. Run\n\n    ```bash\n    yarn install\n    ```\n\n3.\n    Fill the `src/_locales` directory with localization files. Skip this step if they're already there. Either:\n\n    * If you're using `git`:\n\n        `git submodule update --init`\n\n    * If you don't want to use `git`, download them from the `translations` branch and put in `src/_locales` manually.\n\n4.\n    * To build for Gecko (e.g. Firefox):\n\n        ```bash\n        yarn build:gecko\n        ```\n\n    * To build for Chromium (e.g. Chrome, Edge)\n\n        ```bash\n        yarn build:chromium\n        ```\n\n    Bundled files will appear in `./dist-gecko` (or `./dist-chromium`).\n\nFor development build, see [CONTRIBUTING.md](./CONTRIBUTING.md)\n\nThen you can install it on the extensions management page of your browser ([Chromium](https://developer.chrome.com/docs/extensions/mv3/getstarted/#unpacked), [Gecko](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension#installing)).\n\n## Privacy \u0026 security\n\nIn short: it's fine.\n\nAs with practically every other extension, websites you're visiting _may_ detect that you're using this (or alike) extension, and your settings for the extension, by observing:\n\n* playback rate changes of an element.\n* the fact that `createMediaElementSource` has been called for an element.\n* increased frequency of media chunk requests resulting from increased playback rate. This cannot be mitigated with disabling JavaScript.\n* the fact of requesting the same media twice, as a result of using the cloning algotihm.\n\nHowever I doubt that currently there are services that do specifically this. But there may be.\n\nOther than that, there are no known things concerning this. It doesn't interact with third parties or try to do other creepy stuff.\n\n## Why is it free?\n\nIt started out as a hobby project in 2019\nand you could say it remains such today.\nIt feels good to write software that thousands of people use,\nto give back to the humanity.\n\nHowever I am still thinking of monetizing it, in a liberal way.\nI really like\n[FUTO's take on it](https://www.futo.org/about/what-does-futo-believe/),\nand their \"infinite free trial\" thing they do with e.g.\n[FUTO Keyboard](https://keyboard.futo.org/).\n\nHowever, with the current amount of users\nI think it's not worth the effort right now.\n\n\u003cdetails\u003e\u003csummary\u003eAbout donations\u003c/summary\u003e\n\nDonations are great, but what they do is tell the user\n\"we don't really want money, but if you insist, you can send some\",\nor even \"nobody pays for this product,\nso you'll be one of the generous few,\nand if you donate $5 I'll only be able to buy one coffee with it\nand will not really be incentivized to continue the development\".\n\n\u003c!-- Isn't this turning into a blog post rant? --\u003e\nA lot of people are willing to pay. They want to really purchase the product\nand be done with it fair and square\ninstead of running a charity\nand throwing money at the bottomless pit of \"coffees\",\nwondering \"did I give enough?\".\n\nOf course by this I'm not saying I don't appreciate donations.\nThey mean a lot to me. They are more personal.\nI am just describing that in terms of revenue they're not as powerful.\n\n\u003c/details\u003e\n\nAnyways, it is extremely unlikely that this software will go closed-source\nor be sold out,\nespecially given that I am not its only contributor.\nI have already been offered $1000 for it,\nbut this doesn't even cover the hours I spent on it.\nSo, unless it's a life-changing amount of money\n(in which case I'd be able to fund another project like this!),\nI am not really considering it.\n\n## Donate\n\n* \u003chttps://antiwarcommittee.info/en/sunrise/#help\u003e\n* Monero (XMR):\n\n  \u003e \u003cmonero:88yzE5FbDoMVLXUXkbJXVHjNpP5S3xkMaTwBSxmetBDvQMbecMtVCXnQ44W6WRYsPGCPoAYp74ER9aDgBLYDGAAiSt2wu8a?tx_amount=0.050000000000\u0026recipient_name=WofWca%20(https%3A//github.com/WofWca)\u0026tx_description=Donation%20for%20Jump%20Cutter%20extension%20development\u003e\n* Bitcoin (BTC):\n\n  \u003e \u003cbitcoin:bc1qdfz74882mlk64pj4ctpdegvxv9r7jgq8xs2qkxpv3gkv5xqygvgs0fyzm9\u003e\n\u003c!-- * \u003chttps://liberapay.com/WofWca\u003e --\u003e\n\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\n[![AGPLv3 Logo](docs/agplv3-with-text-162x68.png)](./COPYING)\n\n[addons-mozilla-org]: https://addons.mozilla.org/firefox/addon/jump-cutter\n[chrome-web-store]: https://chrome.google.com/webstore/detail/jump-cutter/lmppdpldfpfdlipofacekcfleacbbncp\n[microsoft-edge-addons]: https://microsoftedge.microsoft.com/addons/detail/jlbjhoaphnkkjdafpjomedllppldjkbj\n[weblate]: https://hosted.weblate.org/engage/jump-cutter/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwofwca%2Fjumpcutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwofwca%2Fjumpcutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwofwca%2Fjumpcutter/lists"}