Greasy Fork 支持简体中文。

Storyblocks Audio Downloader

Enables the download button functionality for stock audio.

// ==UserScript==
// @name         Storyblocks Audio Downloader
// @description  Enables the download button functionality for stock audio.
// @icon         https://d3g7htsbjjywiv.cloudfront.net/assets/common/images/logos/unified/storyblocks-icon.svg
// @version      1.0
// @author       afkarxyz
// @namespace    https://github.com/afkarxyz/misc-scripts/
// @supportURL   https://github.com/afkarxyz/misc-scripts/issues
// @license      MIT
// @match        https://www.storyblocks.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function getFormattedFileName(element) {
        const title = element.querySelector('.item-title a').getAttribute('data-selenium-value');
        const tags = Array.from(element.querySelectorAll('.top-tags .tag-wrapper a')).map(tag => tag.textContent.trim());
        return `${tags.join(', ')} - ${title}.mp3`;
    }

    async function downloadFile(url, filename) {
        try {
            const response = await fetch(url);
            const blob = await response.blob();
            const blobUrl = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.style.display = 'none';
            a.href = blobUrl;
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(blobUrl);
            document.body.removeChild(a);
        } catch (error) {
            console.error('Download failed:', error);
        }
    }

    let currentStockId = null;

    const observer = new PerformanceObserver((list) => {
        list.getEntries().forEach((entry) => {
            if (entry.name.toLowerCase().endsWith('.mp3')) {
                const section = document.querySelector(`section[data-stock-id="${currentStockId}"]`);
                if (section) {
                    section.setAttribute('data-mp3-url', entry.name);
                    if (section.getAttribute('data-download-pending') === 'true') {
                        const filename = getFormattedFileName(section);
                        downloadFile(entry.name, filename);
                        section.removeAttribute('data-download-pending');
                    }
                }
            }
        });
    });

    observer.observe({ entryTypes: ['resource'] });

    document.querySelectorAll('section.stock-item').forEach(section => {
        const downloadBtn = section.querySelector('.download-button');
        const playBtn = section.querySelector('.audioPlayButton-button');
        
        downloadBtn.addEventListener('click', async (e) => {
            e.preventDefault();
            const stockId = section.getAttribute('data-stock-id');
            currentStockId = stockId;
            const existingUrl = section.getAttribute('data-mp3-url');
            if (existingUrl) {
                const filename = getFormattedFileName(section);
                await downloadFile(existingUrl, filename);
            } else {
                section.setAttribute('data-download-pending', 'true');
                playBtn.click();
            }
        });
    });
})();