Federated video streaming platform using ActivityPub and P2P in the web browser with Angular. https://joinpeertube.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

241 lines
6.2 KiB

  1. import autocannon, { printResult } from 'autocannon'
  2. import { writeJson } from 'fs-extra'
  3. import { Video, VideoPrivacy } from '@shared/models'
  4. import { createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands'
  5. let server: PeerTubeServer
  6. let video: Video
  7. let threadId: number
  8. const outfile = process.argv[2]
  9. run()
  10. .catch(err => console.error(err))
  11. .finally(() => {
  12. if (server) return killallServers([ server ])
  13. })
  14. function buildAuthorizationHeader () {
  15. return {
  16. Authorization: 'Bearer ' + server.accessToken
  17. }
  18. }
  19. function buildAPHeader () {
  20. return {
  21. Accept: 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
  22. }
  23. }
  24. async function run () {
  25. console.log('Preparing server...')
  26. await prepare()
  27. const tests = [
  28. {
  29. title: 'AP - account peertube',
  30. path: '/accounts/peertube',
  31. headers: buildAPHeader(),
  32. expecter: (body, status) => {
  33. return status === 200 && body.startsWith('{"type":')
  34. }
  35. },
  36. {
  37. title: 'AP - video',
  38. path: '/videos/watch/' + video.uuid,
  39. headers: buildAPHeader(),
  40. expecter: (body, status) => {
  41. return status === 200 && body.startsWith('{"type":"Video"')
  42. }
  43. },
  44. {
  45. title: 'Misc - webfinger peertube',
  46. path: '/.well-known/webfinger?resource=acct:peertube@' + server.host,
  47. expecter: (body, status) => {
  48. return status === 200 && body.startsWith('{"subject":')
  49. }
  50. },
  51. {
  52. title: 'API - unread notifications',
  53. path: '/api/v1/users/me/notifications?start=0&count=0&unread=true',
  54. headers: buildAuthorizationHeader(),
  55. expecter: (_body, status) => {
  56. return status === 200
  57. }
  58. },
  59. {
  60. title: 'API - me',
  61. path: '/api/v1/users/me',
  62. headers: buildAuthorizationHeader(),
  63. expecter: (body, status) => {
  64. return status === 200 && body.startsWith('{"id":')
  65. }
  66. },
  67. {
  68. title: 'API - videos list',
  69. path: '/api/v1/videos',
  70. expecter: (body, status) => {
  71. return status === 200 && body.startsWith('{"total":10')
  72. }
  73. },
  74. {
  75. title: 'API - video get',
  76. path: '/api/v1/videos/' + video.uuid,
  77. expecter: (body, status) => {
  78. return status === 200 && body.startsWith('{"id":')
  79. }
  80. },
  81. {
  82. title: 'API - video captions',
  83. path: '/api/v1/videos/' + video.uuid + '/captions',
  84. expecter: (body, status) => {
  85. return status === 200 && body.startsWith('{"total":4')
  86. }
  87. },
  88. {
  89. title: 'API - video threads',
  90. path: '/api/v1/videos/' + video.uuid + '/comment-threads',
  91. expecter: (body, status) => {
  92. return status === 200 && body.startsWith('{"total":10')
  93. }
  94. },
  95. {
  96. title: 'API - video replies',
  97. path: '/api/v1/videos/' + video.uuid + '/comment-threads/' + threadId,
  98. expecter: (body, status) => {
  99. return status === 200 && body.startsWith('{"comment":{')
  100. }
  101. },
  102. {
  103. title: 'HTML - video watch',
  104. path: '/videos/watch/' + video.uuid,
  105. expecter: (body, status) => {
  106. return status === 200 && body.includes('<title>my super')
  107. }
  108. },
  109. {
  110. title: 'HTML - video embed',
  111. path: '/videos/embed/' + video.uuid,
  112. expecter: (body, status) => {
  113. return status === 200 && body.includes('embed')
  114. }
  115. },
  116. {
  117. title: 'HTML - homepage',
  118. path: '/',
  119. expecter: (_body, status) => {
  120. return status === 200
  121. }
  122. },
  123. {
  124. title: 'API - config',
  125. path: '/api/v1/config',
  126. expecter: (body, status) => {
  127. return status === 200 && body.startsWith('{"client":')
  128. }
  129. }
  130. ]
  131. const finalResult: any[] = []
  132. for (const test of tests) {
  133. console.log('Running against %s.', test.path)
  134. const testResult = await runBenchmark(test)
  135. Object.assign(testResult, { title: test.title, path: test.path })
  136. finalResult.push(testResult)
  137. console.log(printResult(testResult))
  138. }
  139. if (outfile) await writeJson(outfile, finalResult)
  140. }
  141. function runBenchmark (options: {
  142. path: string
  143. headers?: { [ id: string ]: string }
  144. expecter: Function
  145. }) {
  146. const { path, expecter, headers } = options
  147. return new Promise((res, rej) => {
  148. autocannon({
  149. url: server.url + path,
  150. connections: 20,
  151. headers,
  152. pipelining: 1,
  153. duration: 10,
  154. requests: [
  155. {
  156. onResponse: (status, body) => {
  157. if (expecter(body, status) !== true) {
  158. console.error('Expected result failed.', { body, status })
  159. throw new Error('Invalid expectation')
  160. }
  161. }
  162. }
  163. ]
  164. }, (err, result) => {
  165. if (err) return rej(err)
  166. return res(result)
  167. })
  168. })
  169. }
  170. async function prepare () {
  171. server = await createSingleServer(1, {
  172. rates_limit: {
  173. api: {
  174. max: 5_000_000
  175. }
  176. }
  177. })
  178. await setAccessTokensToServers([ server ])
  179. const attributes = {
  180. name: 'my super video',
  181. category: 2,
  182. nsfw: true,
  183. licence: 6,
  184. language: 'fr',
  185. privacy: VideoPrivacy.PUBLIC,
  186. support: 'please give me a coffee',
  187. description: 'my super description'.repeat(10),
  188. tags: [ 'tag1', 'tag2', 'tag3' ]
  189. }
  190. for (let i = 0; i < 10; i++) {
  191. await server.videos.upload({ attributes: { ...attributes, name: 'my super video ' + i } })
  192. }
  193. const { data } = await server.videos.list()
  194. video = data.find(v => v.name === 'my super video 1')
  195. for (let i = 0; i < 10; i++) {
  196. const text = 'my super first comment'
  197. const created = await server.comments.createThread({ videoId: video.id, text })
  198. threadId = created.id
  199. const text1 = 'my super answer to thread 1'
  200. const child = await server.comments.addReply({ videoId: video.id, toCommentId: threadId, text: text1 })
  201. const text2 = 'my super answer to answer of thread 1'
  202. await server.comments.addReply({ videoId: video.id, toCommentId: child.id, text: text2 })
  203. const text3 = 'my second answer to thread 1'
  204. await server.comments.addReply({ videoId: video.id, toCommentId: threadId, text: text3 })
  205. }
  206. for (const caption of [ 'ar', 'fr', 'en', 'zh' ]) {
  207. await server.captions.add({
  208. language: caption,
  209. videoId: video.id,
  210. fixture: 'subtitle-good2.vtt'
  211. })
  212. }
  213. return { server, video, threadId }
  214. }