Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Video Transcoding at Scale for ABC iview (NDC Sydney)

2,376 views

Published on

ABC iview is a video on demand service from the Australian Broadcasting Corporation. In 2015, we built a new service in-house to handle transcoding for all of iview's content.

Metro is built on AWS, and uses FFmpeg, node.js and go components to transcode content quickly and cost-efficiently.

This talk was presented on August 4th 2016 at NDC Sydney.

Published in: Technology
  • Be the first to comment

Video Transcoding at Scale for ABC iview (NDC Sydney)

  1. 1. Video Transcoding at Scale for ABC iview Daphne Chong @daphnechong
  2. 2. metro
  3. 3. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  4. 4. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  5. 5. What changes are we making?
  6. 6. High speed Medium speed Low speed
  7. 7. Standard Encoding H.264 MP4
  8. 8. Transcoding Example
  9. 9. Step 1: Prepare watermark
  10. 10. Step 1: Prepare watermark
  11. 11. Step 1: Prepare watermark
  12. 12. Step 2: Input video (GXF)
  13. 13. Step 3: Asymmetrical cropping
  14. 14. Step 4: Scale and set aspect ratio
  15. 15. Step 5: Apply watermark
  16. 16. Step 6: Ready to stream 1500k
  17. 17. other rendition sizes 1000k 650k 500k 220k audio only
  18. 18. Original file audio track
  19. 19. Previous transcoder audio track
  20. 20. After audio normalisation
  21. 21. That’s a lot of changes...
  22. 22. Transcoding Profiles
  23. 23. GXF, ABC1 Profile: - Renditions (6) - Crop - Normalise audio - Adjust ratio - Add watermark - GXF to MP4
  24. 24. GXF, ABC1
  25. 25. GXF, ABC1 MOV, Arts Profile: - Renditions (6) - Adjust ratio - ProRes MOV to MP4
  26. 26. GXF, ABC1 MOV, Arts
  27. 27. What is this “Magic Video Software” you speak of?
  28. 28. ./ffmpeg -i utopia.gxf utopia.mp4
  29. 29. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  30. 30. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  31. 31. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  32. 32. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  33. 33. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  34. 34. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  35. 35. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  36. 36. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  37. 37. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  38. 38. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  39. 39. ./ffmpeg -i INPUT -c:v libx264 -filter_complex "[0:v]crop=720:576:0:32,yadif,scale=1024x576,setdar=16/9[ma in], [1:v]scale=54:-1[ovrl], [main][ovrl]overlay=main_w-overlay_w-47:main_h-overlay_h-44 " -crf 22 -maxrate 1404k -bufsize 1500k -pix_fmt yuv420p -profile:v high -level 4.0 -refs 3 -r 25 -g 50 -c:a libfdk_aac -b:a 96k -filter_complex "[0:a:0][0:a:1] amerge=inputs=2, dynaudnorm=f=500:g=31:p=0.82:m=30.0:r=0.0:s=0.0 [aout]" -ar 44100 -ac 2 -map 0:0 -map "[aout]" -movflags +faststart -threads 0 -y OUTPUT In reality, it looks like this
  40. 40. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  41. 41. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  42. 42. Cost Scale Flexibility
  43. 43. Cost Scale Flexibility
  44. 44. thesupercarkids.com
  45. 45. mini-me.com
  46. 46. Cost Scale Flexibility
  47. 47. “The Cloud”
  48. 48. Cost Scale Flexibility
  49. 49. Cost Scale Flexibility
  50. 50. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  51. 51. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  52. 52. Source Queue Process Transfer Notify
  53. 53. 8 minutes 27 seconds
  54. 54. Original length Time to produce rendition 60 min 7 min 42 min Lowest (audio) Highest (1500k)
  55. 55. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  56. 56. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  57. 57. Languages: Node.js Go
  58. 58. Node.js Existing team experience Rapid development for APIs Untyped. Sadface.
  59. 59. Go Typed and compiled Cross-platform Easy deployment Learning curve
  60. 60. Infrastructure: EC2, SQS, S3, SNS, Dynamo / RDS, Cloudformation
  61. 61. AWS - EC2 Autoscaling
  62. 62. AWS - SQS Simple Queuing System
  63. 63. SQS First in first out (FIFO) Single consumer per message Message has “visibility timeout” Adjustable visibility timeout
  64. 64. AWS - S3 File Storage
  65. 65. AWS - DynamoDB
  66. 66. AWS - DynamoDB
  67. 67. AWS - DynamoDB AWS - MySQL on RDS
  68. 68. DynamoDB NoSQL Key-value pair storage Pay for number of records/sec read
  69. 69. DynamoDB Our use case was not optimal Manual aggregations Higher cost than expected Doesn’t scale automatically
  70. 70. MySQL Switched to MySQL on RDS Managed hosting Aggregations! Data structure ported as-is
  71. 71. AWS Cloudformation
  72. 72. "ExampleLoadBalancer" : { "Type" : "AWS::ElasticLoadBalancing::LoadBalancer", "Properties" : { "AvailabilityZones" : [ "us-east-1a", "us-east-1b" ], "Listeners" : [ { "LoadBalancerPort" : "80", "InstancePort" : "8081", "Protocol" : "HTTP" } ] } }
  73. 73. Node.js + Go AWS Infrastructure
  74. 74. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  75. 75. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  76. 76. When should you scale?
  77. 77. Scaling Considerations Hourly billing Instance size: Cost vs Speed Content priority Ad-hoc requests Varied content length
  78. 78. Scaling Considerations: AWS limitations AWS scaling metrics can be slow No automatic off switch Can’t choose instances to scale down (Instance protection now available)
  79. 79. MVP: Don’t make things wait too long
  80. 80. MVP: Supply enough capacity at all times
  81. 81. MVP: Driven by drop folders
  82. 82. GXF, ABC1 Profile: - Renditions (2) - Crop - Normalise audio - Adjust ratio - Add watermark - GXF to MP4
  83. 83. var autoscaling = new AWS.AutoScaling(...); var params = { AutoScalingGroupName: groupName, DesiredCapacity: capacity Some white text }; autoscaling.setDesiredCapacity(params, ...);
  84. 84. var autoscaling = new AWS.AutoScaling(...); var params = { AutoScalingGroupName: groupName, DesiredCapacity: capacity Some white text }; autoscaling.setDesiredCapacity(params, ...);
  85. 85. Amazon Machine Images (AMIs)
  86. 86. Which instance size?
  87. 87. Time vs Cost for 1 hour of content Time Cost ?
  88. 88. Winner: c4.xlarge
  89. 89. Up: step scaling Down: stop everything
  90. 90. An interesting puzzle :)
  91. 91. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  92. 92. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  93. 93. 24 hours in Transcoding
  94. 94. (10am - 10am)
  95. 95. $57.22
  96. 96. $42.86 US Dollars
  97. 97. EC2 Instances: $34.31 EC2 (other): $ 4.24 RDS: $ 2.66 S3: $ 1.65 SQS: $ 0.00 Total (USD): $42.86 Transcoding costs: 24 hrs
  98. 98. Next 24 hours Approx 70% of the volume
  99. 99. $34.63 Australian Dollars
  100. 100. One year’s costs?
  101. 101. $16.5k Australian Dollars
  102. 102. $12.5k US Dollars
  103. 103. This is a BIG deal!
  104. 104. thesupercarkids.com
  105. 105. bikesandbeyond.ca
  106. 106. 8 minutes 27 seconds
  107. 107. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  108. 108. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  109. 109. AWS & throughput optimisations
  110. 110. Transcoding in chunks/segments
  111. 111. Introspection & Validation
  112. 112. GXF, ABC1 Profile: - Crop - Normalise audio - Adjust ratio - Add watermark - GXF to MP4
  113. 113. ffprobe
  114. 114. 1. What is Transcoding? 2. Why build our own system? 3. Architecture 4. Technology choices 5. Autoscaling transcoders 6. Costs 7. Future roadmap
  115. 115. Summary
  116. 116. 8 minutes 27 seconds
  117. 117. @daphnechong Thanks!
  118. 118. Q&A

×