# Youtube player frame

Mấy sprint trước mình có nhận 1 task đại khái là cho phép người dùng paste Youtube link (share link, embedded link, shorten link) và hệ thống sẽ tự động lấy thumbnail của Video để hiển thị dạng player frame trong bài viết.

Check qua thì Youtube chỉ hỗ trợ lấy ảnh thumbnail chứ không có cả player frame.

Để lấy ảnh thumbnail thì thậm chí còn không cần phải dùng API để lấy, nó hỗ trợ sẵn theo syntax sau: **https://img.youtube.com/vi/&lt;video\_id&gt;/.jpg**

Trong đó thì **size** có 2 dạng là số nguyên dương và chuỗi, cụ thể như bảng bên dưới:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1700220443253/1660ce90-633d-4fa1-8a4b-98e1c1f3a2fb.png align="left")

Như vậy với bài toán của mình thì lấy luôn ảnh **0.jpg** là đơn giản nhất. Chỉ cần làm sao bóc được ID trong URL mà người dùng paste xong cộng thêm chuỗi URL như Youtube định nghĩa là được.

Vậy làm sao để có ảnh thumbnail trong cái player control khi mà Youtube không hỗ trợ? Chẳng còn cách nào phải chơi fake cả =))

Ý tưởng ở đây là sẽ capture 1 cái player control của Youtube, sau đó xóa nền toàn bộ video đi, chỉ để lại cái player thôi:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1700220444452/fe5ad6bd-cb98-477a-a5f5-94fde71c36c5.png align="left")

Youtube player frame

Tiếp đó lấy ảnh thumbnail của Video, ví dụ: [https://www.youtube.com/watch?v=-tq\_2QHGhqo](https://www.youtube.com/watch?v=-tq_2QHGhqo)

Thì video ID sẽ là **\-tq\_2QHGhqo**, và URL để lấy ảnh thumbnail sẽ là: https://img.youtube.com/vi/**\-tq\_2QHGhqo**/**0**.jpg

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1700220445820/03d589e6-bd5f-4eb5-a1e1-992fa2106393.jpeg align="left")

Ảnh thumbnail mặc định

OK kool, vậy giờ làm sao để ghép giữa ảnh thumbnail và ảnh player frame kia thành một? Có rất nhiều cách, nhưng trong trường hợp của mình thì mình dùng luôn package [Intervention Image](http://image.intervention.io/) cho Laravel

```php
// Backend - create Youtube player frame
$fileName = sprintf('campaigns/videos/%s/%s.jpg', $user->id, md5(time() . $user->id) . $request->video_id);
$frame = storage_path('campaigns/youtube-player-frame-480x360.png');
                
$thumbnail = Image::make(file_get_contents("https://img.youtube.com/vi/{$request->video_id}/0.jpg"))
            ->insert($frame)
            ->stream('jpg', 100);

$isUploaded = Storage::disk('s3-assets')->put($fileName, $thumbnail);

if ($isUploaded) {
  $url = Storage::disk('s3-assets')->url($fileName);
  return $this->response->array(['url' => $url]);
}
```

Tada, work like a charm luôn :)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1700220446963/829e9492-85fc-42a1-b925-50c508f05d1d.jpeg align="left")

Ảnh sau khi ghép player frame + ảnh thumbnail

Bonus thêm đoạn code để lấy ID của video, hỗ trợ các link dạng:

* bình thường
    
* link rút gọn
    
* link nhúng
    

```php
let videoId = '';
const url = video_url.replace(/(>|<)/gi, '').split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/);

if (url[2] !== undefined) {
  videoId = url[2].split(/[^0-9a-z_\-]/i);
  videoId = videoId[0];
}
```

---

Update: Mình có bán source code trên dưới dạng pure PHP để chạy standalone, hỗ trợ chạy cả command line tại [https://www.codester.com/items/29058/generate-youtube-thumbnail-with-player-frame](https://www.codester.com/items/29058/generate-youtube-thumbnail-with-player-frame?ref=donamkhanh) với giá 7$ nha mọi người 😘
