The SHARE button on sound pages is pretty good:
Example page: https://freesound.org/s/674568/
But to make easy linking to sounds with title/license/name attribution as needed in freesound descriptions and forum posts, this can be improved.
This allowed me to create vastly more aesthetically pleasing sound descriptions and forum posts in the past months, avoiding ugly long URLs that are displeasing to read to humans.
For example in https://freesound.org/people/qubodup/sounds/854382/
Or should I say: for example in Big Slow Heavy Drone Hovering Idle Loop (cc0) by qubodup?
A userscript creates such comfy links for me:
// ==UserScript==
// @name Freesound Credits & Filenames
// @namespace http://tampermonkey.net/
// @version 2026-05-17
// @description comfy ui
// @author You
// @match https://freesound.org/people/*/sounds/*/
// @icon https://www.google.com/s2/favicons?sz=64&domain=freesound.org
// @grant none
// ==/UserScript==
// GenAI instructions:
// - Keep these and other comments intact unless they need to be updated
// - Never use unicode icons for decorating comments or logs
// - Do not update the title with version relevant notes, do update the version number
// - Never write comments that are only relevant to a change. Always write generally useful comments that are timeless
// - I'm not interested in occupational therapy, whenever possible give me just one block to replace or write the whole script so I don't have to do chores for the GenAI
(function() {
'use strict';
// fail
function fail(reason) { console.log('[Freesound Credits & Filenames] stopped:', reason); return; }
// not on edit pages
if (window.location.pathname.endsWith('/edit/')) return;
const player = document.getElementsByClassName('bw-player')[0];
if (!player) { fail('player element not found'); return; }
// get id
var id = player.getAttribute('data-sound-id');
// get license
const licenseEl = document.querySelector('body > div.bw-page > div > div > div > div.col-md-4.col-extra-left-padding-large-md > div.bw-sound__sidebar > div.v-spacing-top-5.middle > a');
if (!licenseEl) { fail('license element not found'); return; }
var license = licenseEl.textContent;
const licenseURL = licenseEl.getAttribute('href');
if ( license == 'Creative Commons 0') { license = 'cc0'; }
if ( license == 'Attribution NonCommercial 4.0') { license = 'nc'; }
if ( license == 'Attribution 4.0') { license = 'by'; }
if ( license == 'Sampling+') { license = 's+'; }
// get filename
var title = player.getAttribute('data-title');
// get username
const userEl = document.querySelector('body > div.bw-page > div > div > div > div.col-md-8 > div.bw-sound-page__information.v-spacing-top-5.word-wrap-break-word > div.middle.bw-sound-page__user.v-spacing-top-5 > div.h-spacing-left-1.ellipsis > a');
if (!userEl) { fail('user element not found'); return; }
var user = userEl.textContent;
// filename
var baseName = license + '__' + user + '__' + title + '__' + id;
baseName = baseName.replace(/[/\\?%*:|"<>]/g, '_').replace(/ /g, '-');
// credit info
const ogUrl = document.querySelector('meta[property="og:url"]')?.content;
const ogUsr = document.querySelector('meta[property="og:audio:artist"]')?.content;
const ogSnd = document.querySelector('meta[property="og:audio:title"]')?.content;
const ogUsrUrl = ogUrl?.match(/https:\/\/freesound\.org\/people\/[^/]+\//)?.[0];
const encoded = str =>
str.replace(/&/g, "&")
.replace(/"/g, """)
.replace(/</g, "<")
.replace(/>/g, ">");
var htmls = [
`<a target="_blank" href="${ogUrl}">${ogSnd}</a> (<a target="_blank" href="${licenseURL}">${license}</a>) by <a target="_blank" href="${ogUsrUrl}">${ogUsr}</a>`,
`<a target="_blank" href="${ogUrl}">${ogSnd}</a> (<a target="_blank" href="${licenseURL}">${license}</a>)`,
`<a target="_blank" href="${ogUrl}">${ogSnd}</a> by <a target="_blank" href="${ogUsrUrl}">${ogUsr}</a>`,
`<a target="_blank" href="${ogUrl}">${ogSnd}</a>`
];
var table = '<table class="fs-credit-main-table" style="width: 100%; border-collapse: collapse;">';
// filename row
table += '<tr>';
table += `<td style="padding: 4px;">
<input value="${baseName}" style="width: 100%; border: 1px solid #a2a2b4; padding: 8px; font-family: monospace;" onclick="this.select()" readonly>
</td>`;
table += '</tr>';
// credit rows
for (let i = 0; i < htmls.length; i++) {
table += '<tr>';
table += `<td style="padding: 4px; vertical-align: middle;">
<div class="freesound-credit" contenteditable="true"
style="cursor: text; padding: 8px; border: 1px solid #a2a2b4; background: #fff; color: #000; font-family: sans-serif; font-size: 14px;">
${htmls[i]}
</div>
</td>`;
table += `<td style="padding: 4px;">
<input value="${encoded(htmls[i])}" style="width: 100%; border: 1px solid #a2a2b4; padding: 8px;" onclick="this.select()">
</td>`;
table += '</tr>';
}
table += '</table>';
document.querySelector(
'body > div.bw-page > div > div > div > div.col-md-8 > div:nth-child(1)'
).insertAdjacentHTML('beforeend', table);
const STORAGE_KEY = 'fs_credit_table_hidden';
const mainTable = document.querySelector('.fs-credit-main-table');
if (!mainTable) {
fail('main table not found');
return;
}
const downloadButton = document.querySelector(
'body > div.bw-page > div > div > div > div.col-md-4.col-extra-left-padding-large-md > div.bw-sound__sidebar > div.v-spacing-top-5.v-padding-bottom-5 > a'
);
if (!downloadButton) {
fail('download button not found');
return;
}
mainTable.parentElement.style.position = 'relative';
downloadButton.parentElement.style.position = 'relative';
const hideButton = document.createElement('div');
hideButton.textContent = 'hide';
hideButton.style.position = 'absolute';
hideButton.style.right = '0';
hideButton.style.bottom = '-10px';
hideButton.style.fontSize = '9px';
hideButton.style.color = '#777';
hideButton.style.cursor = 'pointer';
hideButton.style.zIndex = '9999';
const revealArea = document.createElement('div');
revealArea.style.position = 'absolute';
revealArea.style.left = '0';
revealArea.style.top = downloadButton.offsetTop + 'px';
revealArea.style.width = '20%';
revealArea.style.height = downloadButton.offsetHeight + 'px';
revealArea.style.zIndex = '1000';
revealArea.style.cursor = 'pointer';
revealArea.addEventListener('mouseenter', function() {
revealArea.style.background = '#000';
revealArea.style.color = '#fff';
revealArea.style.display = 'flex';
revealArea.style.alignItems = 'center';
revealArea.style.justifyContent = 'center';
revealArea.style.textAlign = 'center';
revealArea.style.fontSize = '11px';
revealArea.style.padding = '2px';
revealArea.textContent = 'show';
});
revealArea.addEventListener('mouseleave', function() {
revealArea.style.background = 'transparent';
revealArea.textContent = '';
});
revealArea.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
localStorage.setItem(STORAGE_KEY, '0');
mainTable.style.display = '';
hideButton.style.display = '';
revealArea.style.display = 'none';
});
hideButton.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
localStorage.setItem(STORAGE_KEY, '1');
mainTable.style.display = 'none';
hideButton.style.display = 'none';
revealArea.style.display = '';
});
mainTable.parentElement.appendChild(hideButton);
downloadButton.parentElement.appendChild(revealArea);
const hidden = localStorage.getItem(STORAGE_KEY) === '1';
if (hidden) {
mainTable.style.display = 'none';
hideButton.style.display = 'none';
revealArea.style.display = '';
} else {
revealArea.style.display = 'none';
}
document.querySelectorAll('.freesound-credit').forEach(el => {
el.addEventListener('click', function() {
var range = document.createRange();
range.selectNodeContents(this);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
});
});
document.querySelectorAll('.freesound-credit').forEach(el => {
el.addEventListener('copy', function(e) {
e.preventDefault();
const selection = window.getSelection();
const container = document.createElement('div');
container.appendChild(selection.getRangeAt(0).cloneContents());
const cleanHTML = container.innerHTML;
e.clipboardData.setData('text/plain', selection.toString());
e.clipboardData.setData('text/html', cleanHTML);
});
});
})();
The UI:
This could be put in the share sidebar area. The left side should be right aligned so users can easily see which version includes license/name.
I would also recommend local storage to be used to remember site wide whether the share area should be permanently unfolded. I for one have it open most of the time.
Forum
I recommend the same for forum threads. Human readable thread links like the following instead of ugly URLs:
This is achieved with this userscript:
// ==UserScript==
// @name Freesound Forum Link Snippet
// @namespace http://tampermonkey.net/
// @version 2026-04-26
// @description Adds self-selecting HTML snippet + preview for forum threads
// @match https://freesound.org/forum/*/*/
// @icon https://www.google.com/s2/favicons?sz=64&domain=freesound.org
// @grant none
// ==/UserScript==
(function () {
'use strict';
const titleEl = document.querySelector('h3');
if (!titleEl) return;
const title = titleEl.textContent.trim();
const url = document.querySelector('meta[property="og:url"]')?.content || window.location.href;
// extract + normalize date
const metaText = document.querySelector('.text-grey.v-spacing-7')?.textContent || '';
let date = '';
const match = metaText.match(/Started\s+([A-Za-z]+\s+\d{1,2}\w{2},\s+\d{4})/);
if (match) {
const d = new Date(match[1]);
if (!isNaN(d)) {
date = d.toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
});
} else {
date = match[1];
}
}
const encoded = str =>
str.replace(/&/g, "&")
.replace(/"/g, """)
.replace(/</g, "<")
.replace(/>/g, ">");
// DATE OUTSIDE LINK
const html = date
? `<a target="_blank" href="${url}">${title}</a> (${date})`
: `<a target="_blank" href="${url}">${title}</a>`;
const plain = date
? `${title} (${date}) - ${url}`
: `${title} - ${url}`;
const box = document.createElement('div');
box.style.margin = '10px 0';
box.innerHTML = `
<table style="width:100%; border-collapse:collapse;">
<tr>
<td style="padding:4px;">
<div class="fs-preview"
style="cursor:text; padding:8px; border:1px solid #a2a2b4; background:#fff; color:#000;">
${html}
</div>
</td>
<td style="padding:4px;">
<input value="${encoded(html)}"
style="width:100%; border:1px solid #a2a2b4; padding:8px; font-family:monospace;"
readonly onclick="this.select()">
</td>
</tr>
<tr>
<td colspan="2" style="padding:4px;">
<input value="${plain}"
style="width:100%; border:1px solid #a2a2b4; padding:8px;"
readonly onclick="this.select()">
</td>
</tr>
</table>
`;
// INSERT AT TOP (before header block)
const container = titleEl.closest('.col-12.no-paddings.v-spacing-5');
if (container) {
container.insertBefore(box, container.firstChild);
}
// select-on-click + clean copy
box.querySelectorAll('.fs-preview').forEach(el => {
el.addEventListener('click', () => {
const range = document.createRange();
range.selectNodeContents(el);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
});
el.addEventListener('copy', (e) => {
e.preventDefault();
const selection = window.getSelection();
const container = document.createElement('div');
container.appendChild(selection.getRangeAt(0).cloneContents());
e.clipboardData.setData('text/plain', selection.toString());
e.clipboardData.setData('text/html', container.innerHTML);
});
});
})();
which provides an easy to copy snippet:
The SHARE button on sound pages is pretty good:
Example page: https://freesound.org/s/674568/
But to make easy linking to sounds with title/license/name attribution as needed in freesound descriptions and forum posts, this can be improved.
This allowed me to create vastly more aesthetically pleasing sound descriptions and forum posts in the past months, avoiding ugly long URLs that are displeasing to read to humans.
For example in https://freesound.org/people/qubodup/sounds/854382/
Or should I say: for example in Big Slow Heavy Drone Hovering Idle Loop (cc0) by qubodup?
A userscript creates such comfy links for me:
The UI:
This could be put in the share sidebar area. The left side should be right aligned so users can easily see which version includes license/name.
I would also recommend local storage to be used to remember site wide whether the share area should be permanently unfolded. I for one have it open most of the time.
Forum
I recommend the same for forum threads. Human readable thread links like the following instead of ugly URLs:
This is achieved with this userscript:
which provides an easy to copy snippet: