1

我想显示我拥有 Track-URL 的 soundcloud 轨道的艺术图像。

我知道当我从 URL 中提取轨道键/ID 时,我可以通过他们的 API 请求艺术品 URL,然后将检索到的 URL 注入到图像标签中。

我想知道的是,是否可以使用某种 URL 模式使 soundcloud 将浏览器转发到正确的艺术品 URL,就像它可能使用 facebook 个人资料图像一样。

例如:

马克扎克伯格目前的头像有网址http://profile.ak.fbcdn.net/hprofile-ak-prn2/t5/202896_4_1782288297_q.jpg

那是一些神秘的东西,因为它托管在 CDN 上。Soundcloud 艺术作品 URL 看起来也很神秘。

现在,当我知道标记 facebook id/key(“zuck”)时,我可以像这样简单地访问他的个人资料图片:

http://graph.facebook.com/zuck/picture

该 URL 由 facebook API 自动转发到个人资料图片 URL。

使用此 URL 模式,您不仅可以抽象出额外 API 请求的原因,而且还可以保证处理时间。

soundcloud 轨道艺术作品有这样的功能吗?

4

2 回答 2

1

我写了一个快速应用程序,它重定向到他们 CDN 上最大的可用图像,给定artwork_url.

FixSoundCloudArtworkUrl.js

它使用它们的命名方案并一一枚举大小,直到某些图像返回状态 200。

资源:

'use strict';

var express = require('express'),
    app = express();

require('./config/development')(app, express);
require('./config/production')(app, express);

var redis = require('redis'),
    request = require('request'),
    Promise = require('bluebird');

Promise.promisifyAll(redis.RedisClient.prototype);

var redisSettings = app.set('redis'),
    redisClient = redis.createClient(redisSettings.port, redisSettings.host, redisSettings.options);

app.configure(function () {
  app.use(express.bodyParser());
  app.use(app.router);
});

function sendError(res, status, error) {
  if (!(error instanceof Error)) {
    error = new Error(JSON.stringify(error));
  }

  return res
    .status(status || 500)
    .end(error && error.message || 'Internal Server Error');
}

function generateCacheHeaders() {
  var maxAge = 3600 * 24 * 365;

  return {
    'Cache-Control': 'public,max-age=' + maxAge,
    'Expires': new Date(Date.now() + (maxAge * 1000)).toUTCString()
  };
}

function getCacheKey(url) {
  return 'soundcloud-thumbnail-proxy:' + url;
}

app.get('/*', function (req, res) {
  var originalUrl = req.params[0],
      cacheKey = getCacheKey(originalUrl),
      urls;

  // https://developers.soundcloud.com/docs/api/reference#artwork_url
  // This is a ridiculous naming scheme, by the way.

  urls = [
    originalUrl,
    originalUrl.replace('-large', '-t500x500'),
    originalUrl.replace('-large', '-crop'), // 400x400
    originalUrl.replace('-large', '-t300x300'),
    originalUrl.replace('-large', '-large') // 100x100
  ];

  return redisClient.getAsync(cacheKey).then(function (cachedUrl) {
    if (cachedUrl) {
      return cachedUrl;
    }

    return Promise.reduce(urls, function (resolvedUrl, url) {
      if (resolvedUrl) {
        return resolvedUrl;
      }

      return new Promise(function (resolve) {
        request.head(url, function (err, response) {
          if (!err && response.statusCode === 200) {
            resolve(url);
          } else {
            resolve(null);
          }
        });
      });
    }, null);
  }).then(function (url) {
    if (!url) {
      throw new Error('File not found');
    }

    var headers = generateCacheHeaders();
    for (var key in headers) {
      if (headers.hasOwnProperty(key)) {
        res.setHeader(key, headers[key]);
      }
    }

    res.redirect(url);
    redisClient.set(cacheKey, url);
    redisClient.expire(cacheKey, 60 * 60 * 24 * 30);

  }).catch(function (err) {
    sendError(res, 404, err);
  });

});

app.get('/crossdomain.xml', function (req, res) {
  req.setEncoding('utf8');
  res.writeHead(200, { 'Content-Type': 'text/xml' });
  res.end('<?xml version="1.0" ?><cross-domain-policy><allow-access-from domain="*" /></cross-domain-policy>');
});

redisClient.on('ready', function () {
  app.listen(app.set('port'));
});

redisClient.on('error', function () {
  throw new Error('Could not connect to Redis');
});

module.exports = app;
于 2014-11-07T17:03:51.773 回答
0

没有。唯一记录在案的方法是:“/tracks”的 API 参考

于 2014-02-08T22:43:44.130 回答