Välisvideo avaldamine Twitteris - Node.js versioon

Kuidas piltide või videote avaldamine üldiselt Twitter API-ga töötab?

See, kuidas pilti või videot twitteris avaldatakse, hõlmab rohkem kui ühte sammu. Esiteks peate meediumid üles laadima twitterisse üleslaadimisliidese API abil.
See tagastab üleslaaditud meediumile ID. Nüüd peate teisel sammul uue säutsu avaldamiseks helistama Twitteri API-le. Sellele API-le helistades peate täpsustama meediumide ID, nii et twitter sisaldab üleslaaditud meediume selle säutsu abil. Allpool on uue säutsu avaldamise API.

Meediumi üleslaadimiseks Twitterisse on kaks võimalust

Otsene üleslaadimine: meediume saab üles laadida, kasutades Twitteri POST-meediumit / üleslaadimisliidest. See on lihtne pildi üleslaadimise lõpp-punkt, mis ei paku kõiki funktsioone. See API toetab ainult teatud tüüpi meediume, mis ei hõlma gif- ja videofilme. Nii et saate selle rakendusliidese abil lihtsalt üles laadida tüüpi pilti kandvaid meediume. Isegi pildi jaoks on suurusepiirang umbes 3 MB. Seda ei ole ametlikult dokumenteeritud, kuid paljud arendajad on selle API kasutamise ajal seda piirangut ületanud. Vastus tagastab media_id (või media_id_string), mille saab seejärel edastada ülalmainitud POST-i olekute / värskendusliidesega.

Tükeldatud üleslaadimine: otsese üleslaadimise alternatiiv on tükeldatud üleslaadimise lõpp-punkt. Kandja on jagatud mitmeks tükiks. Seejärel laaditakse iga tükk üksteise järel eraldi. Pärast kõigi osade üleslaadimist saab media_id (või media_id_string) POST-olekute / värskendustega edasi anda.

Järgnevalt on toodud erinevad API-d, mis koos muudavad meediumide chunked-üleslaadimise edukaks.

INIT - käsu INIT käsku kasutatakse faili üleslaadimisseansi algatamiseks. Tagastab media_id, mida tuleks kasutada kõigi järgnevate taotluste täitmiseks.

LISA - käsku APPEND kasutatakse meediumifaili tüki üleslaadimiseks. Faili võib jagada tükkideks ja üles laadida, kasutades käske APPEND. Iga tüki jaoks tuleb kutsuda eraldi käsk APPEND.

FINALIZE - käsk FINALIZE tuleks kutsuda pärast kogu meediumifaili üleslaadimist käskude APPEND abil.

Olek - kui käsu FINALIZE vastus sisaldab väljat töötlus_info, võib osutuda vajalikuks kasutada ka Olekut ja oodata, kuni see edu tagasi saab. STATUS-käsku kasutatakse meediumitöötluse toimingute värskenduste perioodiliseks küsitluseks. Kui käsu STATUS vastuse tagastamine õnnestub, võite liikuda järgmise Tweet loomise sammu juurde.

Miks on tükeldatud üleslaadimine parem?

Tükeldatud üleslaadimise API toetab staatilisi pilte, animeeritud gife ja ka videoid. See tagab parema töökindluse. Twitter soovitab seda meedia üleslaadimiseks. See võimaldab ka failide üleslaadimise peatada ja jätkata, mis tähendab, et saate oma rakenduse kasutajatel lubada meedia üleslaadimist peatada ja jätkata. See on aeglaste ühenduste jaoks äärmiselt vajalik. Samuti on Twitter selgelt öelnud, et uusi funktsioone toetatakse ainult tükeldatud üleslaadimise lõpp-punktidele.

Tõhusa chunked-üleslaadimise näiteid pole piisavalt

Pole ühtegi kogu, mis võimaldaks hõlpsalt meediat tükkideks üles laadida. Samuti pole saadaval piisavalt näiteid, et hakata iseseisvalt tükeldatud üleslaadimist rakendama. Isegi kui Chunked Uploadi näitamiseks on vähe näiteid, loodavad nad kõik, et meediumid asuvad teie kohalikul masinal.
Näited, mille leidsin, olid -
github.com/desmondmorris/node-twitter - see näitab, kuidas meediumit tükkideks üles laadida, kui see asub kohalikul teel.
lorenstewart.me/twitter-api-uploading-videos-using-node-js - kasutage Twiti teeki, kuid see näitab jällegi, kuidas kohalikku meediat saab üles laadida.

Ilmselt saate faili välisest URL-ist või S3-st või muust kohast oma arvutisse alla laadida ja rakendada ülaltoodud meetodeid tükkideks üleslaadimiseks. Seejärel saate allalaaditud meediumid kohalikust arvutist puhastada.
Kuid kas poleks parem, kui me saaksime lihtsalt voogesitada meediat väliselt teelt Twitterisse tükkideks. Nii ei pea me muretsema kraami puhastamise pärast, samuti ei pea me alla laadima kogu faili ja alustama siis tükeldatud üleslaadimist. Tüki üleslaadimine võib olla palju tõhusam, kui suudame ülaltoodud viisist lahti saada.

Kuidas saaksime seda Node.js-ga rakendada?

Ülevaade Chunked üleslaadimisest Twitterisse

(Pange tähele, et allpool olev kood kasutab enamuses selle rakendamisest saagikuse generaatori paradigmat. Algse teostuse lülitamiseks aga asünkrooni-ootusele. Nii leiate palju saagikuse generaatori stiiliga koodi koos vähese viitega lubadustele ja tagasilükkamistele. Erinevate stiilide vahel vahetamiseks kasutame bluebird-teeki.)

Määratleme kõigepealt meie põhiobjektid, mida tuleb funktsioonidele edasi anda.

oAuthCredentials sisaldab kõiki twitteri mandaatidega seotud atribuute, mida on vaja twitteri API-dele juurdepääsuks.

const oAuthCredentials = {
  'tarbija_klahv': 'TFtxxxxxxxxxxDtR4',
  'Consumer_secret': 'gjWH7xxxxxxxxxxxxxlQz',
  'sümboolne': '41xxxxx72–8Qaxxxxxxxxxxxx6aN',
  'token_secret': 'bt8xxxxxxxxxxxxxxh7v9'
}

videoObj sisaldab video URL-i, aga ka muid metaandmeid nagu kõrgus, laius, kestus jne.

const videoObj = {
  originalUrl: 'https://tw-media-poc.s3.amazonaws.com/742ee.mp4',
  videoMeta: {
    kõrgus: 123,
    laius: 234,
    suurus: 1685018,
    kestus: 120,
    mimeType: 'video / mp4'
  }
}

Kirjutagem nüüd funktsioonid igaks osaks üles laaditud Twitter API käsust.

Käsk Init - INIT nõuab video üksikasju, näiteks mimeType (mp4, MPEG jne) ja suurus baitides. Tagastab mediaId, mida tuleb kasutada järgmistes käskudes.

const _initMediaUpload = function * (oAuthCredentials, videoObj) {
  const options = {
    URL: 'https://upload.twitter.com/1.1/media/upload.json',
    oauth: oAuthCredentials,
    formData: {
      käsk: 'INIT',
      'media_type': videoObj.videoMeta.mimeType,
      'media_category': 'tweet_video',
      'kokku_bytes': videoObj.videoMeta.size
    }
  }
  proovige {
    const resultArray = saagikogus requestPost (valikud)
    const resp = resultArray [0]
    const body = resultArray [1]
    const mediaId = JSON.parse (body) .media_id_string
    return mediaId
  } saagi (viga) {
    viska viga
  }
}

Lisamine - käsk APPEND aktsepteerib andmemahtu base64-vormingus koos mediaId ja tüki numbriga, st segment_index. Seda käsku tuleks kutsuda üks kord iga tüki jaoks.

const _appendMediaUpload = funktsioon * (oAuthCredentials, data, mediaId, segmentIndex) {
  const options = {
    URL: 'https://upload.twitter.com/1.1/media/upload.json',
    oauth: oAuthCredentials,
    vorm: {
      käsk: 'APPEND',
      'media_id': mediaId,
      'segment_index': segmentIndex,
      // meedium: andmed
      'media_data': data.toString ('base64')
    }
  }
  proovige {
    const resultArray = saagikogus requestPost (valikud)
    tagasi
  } saagi (viga) {
    viska viga
  }
}

Lõpeta - käsk FINALIZE tuleks kutsuda, kui kõik tükid on käsu APPEND abil üles laaditud. Selle eesmärk on öelda Twitterile, et enam ühtegi tükki pole jäänud.

const _finalizeMediaUpload = function * (oAuthCredentials, mediaId) {
  const options = {
    URL: 'https://upload.twitter.com/1.1/media/upload.json',
    oauth: oAuthCredentials,
    formData: {
      käsk: 'FINALIZE',
      'media_id': mediaId
    }
  }
  proovige {
    const resultArray = saagikogus requestPost (valikud)
    tagasi
  } saagi (viga) {
    viska viga
  }
}

Olek - käsk STATUS tagastab üleslaaditud meediumi oleku. Selle põhjuseks on asjaolu, et Twitter töötleb üleslaaditud meediume teatud tüüpi. Kui olekut ei õnnestu, ei saa vastavat mediaId POST-i olekute / värskendusliidese API-ga kasutada. Seega tuleks alati oodata, kuni käsk STAATUS taastab oleku, nagu õnnestus.

const _getStatusMediaUpload = function * (oAuthCredentials, mediaId, lastProgressPercent) {
  const options = {
    URL: 'https://upload.twitter.com/1.1/media/upload.json',
    oauth: oAuthCredentials,
    qs: {
      käsk: 'STATUS',
      'media_id': mediaId
    }
  }
  proovige {
    const resultArray = saagikutse saamine (valikud)
    const body = JSON.parse (resultArray [1])
    if (keha ['töötlemise_info']) {
      // kui töötlemise teave on olemas, tagastage see
      const processingInfo = body ['processing_info']
      tagasta töötlemineInfo
    } else if (body.errors) {
      // kui keha sisaldab vigu, ehitage teade ja looge tõrge
      const message = _.get (sisu, 'kļūdas.0.teade')
      const kood = _.get (põhiosa, 'kļūdas.0.kood')
      viska uus viga (`$ {code} $ {message}`)
    } veel {
      // else tagastab kohandatud töötlemise teabe
      const processingInfo = {
        olek: “teadmata”,
        'progress_percent': lastProgressPercent
      }
      tagasta töötlemineInfo
    }
  } saagi (viga) {
    viska viga
  }
}

Pange tähele, et ülaltoodud lõikudes on requestPost & requestGet vaid lubadusega funktsioonid päringute teegi ülaosas. Samuti tähistab _ lodashi raamatukogu.

const _ = nõuda ('lodash')
const request = nõuda ('request')
const Lubadus = nõuda ('bluebird')
const requestPost = Lubadus.komprimeerida (request.post, {multiArgs: true})
const requestGet = Promise.promisify (request.get, {multiArgs: true})

Proovime nüüd integreerida kõik tükid omavahel. Esmalt proovime siduda APPEND & FINALIZE osa, mis tegeleb otse üleslaadimisega. Selleks avame videofaili andmete toomiseks voo. Lähenemisviis erineb olenevalt sellest, kus video asub. Olen mõlemat viisi kommentaaridega maininud.

Sündmuste ärakasutamiseks pöördume tagasi tagasihelistamise stiili juurde. Promise.coroutine aitab meil helistada generaatori funktsioonidele tagasihelistamise põhises voos.

Mitte-ok-HTTP-koodiga tõrke- ja vastussündmuse korral saadame vea. Andmesündmuse jaoks käsitleme neid andmeid tükkidena ja proovime faili _appendMediaUpload abil twitterisse üles laadida. Kui kõik tükid on üles laaditud, kutsume funktsiooni _finalizeMediaUpload, et öelda Twitterile, et oleme kõik tükid üles laadinud. See samm võib juhtuda kas andmete või lõppsündmuse korral. Andmete ja sündmuse lõpu sünkroonimiseks kasutame selliseid muutujaid nagu chunkUploadInProgress ja streamReadingEnded.

const _streamMediaToTwitter = funktsioon (oAuthCreds, videoObj, mediaId, cb) {
  lase segmentIndex = 0
  lase chunkUploadInProgress = false
  lase streamReadingEnded = false
  // kui video URL on S3
  const filePath = videoObj.originalUrl
  const indexOfForwardSlash = filePath.lastIndexOf ('/')
  const fileName = (indexOfForwardSlash! == -1)? filePath.substr (indexOfForwardSlash + 1): filePath
  const startIndex = 'https: //'.length
  const endIndex = filePath.indexOf ('. s3.amazonaws.com')
  const bucket = filePath.slice (startIndex, endIndex)
  const params = {
    Kopp: kopp,
    Võti: failinimi
  }
  const res = s3.getObject (parameetrid) .createReadStream ()
  // kui video URL on väline URL
  const res = request.get (videoObj.originalUrl)
  res.on ('vastus', funktsioon (resp) {
    if (resp.statusCode! == 200) {
      const error = uus viga (`taotlus nurjus: $ {resp.statusCode}`)
      res.resume ()
      tagastamise cb (viga)
    }
  })
  res.on ('tõrge', funktsioon (viga) {
    tagastamise cb (viga)
  })
  res.on ('andmed', funktsioon (tükk) {
    res.pause ()
    chunkUploadInProgress = tõsi
    Promise.coroutine (_appendMediaUpload) (oAuthCreds, tükk, mediaId, segmentIndex)
      . seejärel (() => {
        segmentIndex ++
        res.resume ()
        chunkUploadInProgress = vale
        Promise.resolve ()
      })
      . seejärel (() => {
        if (! chunkUploadInProgress && streamReadingEnded) {
          Promise.coroutine (_finalizeMediaUpload) (oAuthCreds, mediaId)
            . seejärel (() => {
              tagastamise cb (null, mediaId)
            })
        }
      })
      .catch ((viga) => cb (err))
  })
  res.on ('lõpp', funktsioon () {
    streamReadingEnded = tõene
    if (! chunkUploadInProgress && streamReadingEnded) {
      Promise.coroutine (_finalizeMediaUpload) (oAuthCreds, mediaId)
        . seejärel (() => {
          tagastamise cb (null, mediaId)
        })
    }
  })
}

Nüüd ühendage ülejäänud osad ülaltoodud funktsiooniga, mille me kirjutasime meedia voogesitamiseks Twitterisse. Ülejäänud osad hõlmavad kõige esimest ja viimast sammu, st _initMediaUpload, mis tegelikult algatab meediumide üleslaadimise & _getStatusMediaUpload, mis annab üleslaaditud meediumite töötlemise oleku. Peame siin olekut korduvalt kontrollima.

// algatage meediumi üleslaadimine ja hankige mediaId
const mediaId = saagis _initMediaUpload (oAuthCredentials, videoObj)
    
// voog video URL-ist twitterisse
saagis Promise.promisify (_streamMediaToTwitter) (oAuthCredentials, videoObj, mediaId)
// kontrollige olekut ja oodake, kuni meediumide üleslaadimine on lõppenud
lase olek = 'ootel'
lase progressPercent = 0 // edusammude kontrollimiseks saate selle printida
const startTime = Date.now ()
tee {
  const töötlemineInfo = saagis _getStatusMediaUpload (oAuthCredentials, mediaId, progressPercent)
  olek = processingInfo.state
  progressPercent = processingInfo.progress_percent
} while (olek! == 'õnnestus' && (Date.now () - startTime) <30 * 1000)

Nüüd oleme sidunud kõik tükid, mis on vajalikud meedia üleslaadimiseks Twitterisse.

Mõned punktid -

  • Edenemise staatust kontrollides kontrollige kindlasti teatud aja möödudes väljumisteed. (Date.now () - startTime) <30 * 1000 - see tingimus oli sellel täpselt olemas.
  • Rakendus on seotud videoga, kuid seda saab kasutada isegi väiksemate muudatustega piltide jaoks, näiteks vahetades meediumikategooriat INIT-i toimingus.
  • Twitteris on vastuvõetavate videote jaoks ranged tingimused, mida saab API kaudu Twitterisse avaldada, ja enne üleslaadimise alustamist veenduge, et teie video on kindlalt lubatud piirides. Piirangud on loetletud siin.

See lähenemisviis on kasulik isegi Facebooki jaoks

Teil oleks hea meel teada saada, et isegi Facebooki API järgib sarnaseid mõisteid nagu Twitter meediumide üleslaadimiseks.

Facebook pakub meedia üleslaadimiseks 2 viisi, nagu ka Twitter. Facebook nimetab neid mitte-jätkatavaks üleslaadimiseks ja jätkamiseks. Jätkatav üleslaadimine sarnaneb Chunked üleslaadimisega Twitteris. Sellel on mitu sammu, mis vastavad Twitteris varem kirjeldatud käskudele. Lisateavet Facebooki jätkatava üleslaadimise kohta leiate siit.

Nii et kui kirjutate koodi Twitteri tükeldatud üleslaadimiseks. Saate muuta üldiseks ka selle, et saaks hakkama ka Facebooki meediumide üleslaadimisega.

Selle ülesande kallale asudes seisin silmitsi paljude raskustega, et kõik toimiks Node.js suhtes. Nii et kui suutsin kõik õigesti kirja panna, otsustasin kirjutada selle postituse. Loodan, et sellest on kellelegi abi. Terviseks!