Skip to content

Commit

Permalink
Add basic stream player
Browse files Browse the repository at this point in the history
  • Loading branch information
ngrie committed Jun 2, 2020
1 parent 2c8ec7d commit cdffde6
Show file tree
Hide file tree
Showing 17 changed files with 219 additions and 44 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 15,7 @@

RTMP_THUMBNAILS_BASE_URL=http://127.0.0.1:8081/thumbnails/
RTMP_CONTROL_MODULE_BASE_URL=http://127.0.0.1:8081/control/
RTMP_HTTP_FLV_BASE_URL=http://127.0.0.1:8081/live

###> symfony/framework-bundle ###
APP_ENV=dev
Expand Down
6 changes: 6 additions & 0 deletions assets/css/tailwind.css
Original file line number Diff line number Diff line change
@@ -0,0 1,6 @@
/* purgecss start ignore */
@tailwind base;
@tailwind components;
/* purgecss end ignore */

@tailwind utilities;
2 changes: 2 additions & 0 deletions assets/js/admin/fontawesome.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 9,7 @@ import { faClipboard } from '@fortawesome/free-solid-svg-icons'
import { faChevronLeft } from '@fortawesome/free-solid-svg-icons'
import { faTrash } from '@fortawesome/free-solid-svg-icons'
import { faRedo } from '@fortawesome/free-solid-svg-icons'
import { faPlay } from '@fortawesome/free-solid-svg-icons'

library.add(
faUser,
Expand All @@ -20,4 21,5 @@ library.add(
faChevronLeft,
faTrash,
faRedo,
faPlay,
)
31 changes: 24 additions & 7 deletions assets/js/admin/pages/Streams/StreamItem.vue
Original file line number Diff line number Diff line change
@@ -1,12 1,22 @@
<template>
<StreamListItem :first="first">
<template #image>
<img
v-if="stream.live && thumbnailUrl"
class="h-16 w-20 object-cover rounded shadow"
:src="thumbnailUrl" alt=""
/>
<div v-else class="border-4 border-dashed border-gray-200 rounded-lg h-16 w-20"></div>
<div class="relative group">
<img
v-if="stream.live && thumbnailUrl"
class="h-16 w-20 object-cover rounded shadow"
:src="thumbnailUrl" alt=""
/>
<div v-else class="border-4 border-dashed border-gray-200 rounded-lg h-16 w-20"></div>
<div
v-if="stream.live"
class="hidden absolute top-0 left-0 group-hover:flex items-center justify-center w-full h-full cursor-pointer rounded"
:class="{ 'hover:bg-white hover:bg-opacity-50': thumbnailUrl }"
@click="openStreamPlayer"
>
<fa-icon :icon="['fas', 'play']" />
</div>
</div>
</template>
<template #details>
<div class="text-sm leading-loose text-gray-900">
Expand Down Expand Up @@ -59,7 69,7 @@
import notificationMixin from 'mixins/notification'
import Badge from 'ui/Badge'
import StreamListItem from 'ui/streamList/StreamListItem'
import { generateErrorMessageFromResponse, getRtmpPrefix } from 'utils'
import { config, generateErrorMessageFromResponse, getRtmpPrefix } from 'utils'
import StreamingCredentialsModal from './StreamingCredentialsModal'
import CredentialsWrapper from '../../components/CredentialsWrapper'
import DropPublisherConfirmDialog from './DropPublisherConfirmDialog'
Expand Down Expand Up @@ -111,6 121,13 @@
this.showErrorNotification(generateErrorMessageFromResponse('Publisher could not be kicked from the stream.', response))
}
},
openStreamPlayer() {
window.open(
config('baseUrl') 'play/' this.stream.slug,
'_blank',
'width=900,height=500,toolbar=0,location=0,menubar=0',
)
},
},
}
</script>
37 changes: 37 additions & 0 deletions assets/js/publicPlayer.js
Original file line number Diff line number Diff line change
@@ -0,0 1,37 @@
import FlvJs from 'flv.js'
import { library, icon } from '@fortawesome/fontawesome-svg-core'

import '../css/tailwind.css'

import { faPlay } from '@fortawesome/free-solid-svg-icons'
library.add(faPlay)

document.getElementById('buttonIcon').innerHTML = icon({
prefix: 'fas',
iconName: 'play',
}).html

document.getElementById('playButton').addEventListener('click', () => {
document.getElementById('buttonWrapper').remove()
if (FlvJs.isSupported()) {
const playerEl = document.createElement('video')
playerEl.autoplay = true
playerEl.controls = true
playerEl.classList.add('w-screen')
playerEl.classList.add('h-screen')
document.getElementsByTagName('body')[0].appendChild(playerEl)


const player = FlvJs.createPlayer({
type: 'flv',
isLive: true,
url: stream_url,
})
player.attachMediaElement(playerEl)
player.load()
player.play()
setInterval(() => {
player.play()
}, 1000)
}
})
2 changes: 2 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 6,7 @@
parameters:
rtmp_thumbnails_base_url: '%env(resolve:RTMP_THUMBNAILS_BASE_URL)%'
rtmp_control_module_base_url: '%env(resolve:RTMP_CONTROL_MODULE_BASE_URL)%'
rtmp_http_flv_base_url: '%env(resolve:RTMP_HTTP_FLV_BASE_URL)%'

services:
# default configuration for services in *this* file
Expand All @@ -15,6 16,7 @@ services:
bind:
$rtmpThumbnailsBaseUrl: '%rtmp_thumbnails_base_url%'
$rtmpControlModuleBaseUrl: '%rtmp_control_module_base_url%'
$rtmpHttpFlvBaseUrl: '%rtmp_http_flv_base_url%'

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
Expand Down
1 change: 1 addition & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 64,7 @@ ENV DATABASE_URL mysql://root:rtmpie@database:3306/rtmpie?serverVersion=mariadb-
ENV MERCURE_PUBLISH_URL http://mercure/.well-known/mercure
ENV RTMP_THUMBNAILS_BASE_URL http://rtmp/thumbnails/
ENV RTMP_CONTROL_MODULE_BASE_URL http://rtmp/control/
ENV RTMP_HTTP_FLV_BASE_URL /live

RUN composer install --prefer-dist --no-dev --no-progress --no-suggest --no-interaction --optimize-autoloader; \
composer dump-autoload --no-dev --classmap-authoritative; \
Expand Down
5 changes: 5 additions & 0 deletions docker/nginx-rtmp/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 13,11 @@ http {
location /control {
rtmp_control all;
}

location /live {
flv_live on;
chunked_transfer_encoding on;
}
}
}

Expand Down
78 changes: 44 additions & 34 deletions docker/nginx/conf.d/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 6,48 @@ server {
}

location ~ ^/index\.php(/|$) {
fastcgi_pass php:9500;

# Increase the buffer size to handle large cache invalidation headers
fastcgi_buffer_size 32k;
fastcgi_buffers 32 4k;

fastcgi_split_path_info ^(. \.php)(/.*)$;
include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;

# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/index.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}

# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}

location ^~ /.well-known/mercure {
proxy_pass http://mercure;
proxy_read_timeout 24h;
proxy_http_version 1.1;
proxy_set_header Connection "";

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
fastcgi_pass php:9500;

# Increase the buffer size to handle large cache invalidation headers
fastcgi_buffer_size 32k;
fastcgi_buffers 32 4k;

fastcgi_split_path_info ^(. \.php)(/.*)$;
include fastcgi_params;

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;

# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/index.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}

# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}

location ^~ /.well-known/mercure {
proxy_pass http://mercure;
proxy_read_timeout 24h;
proxy_http_version 1.1;
proxy_set_header Connection "";

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}

location = /live {
set $args $args&port=1935&app=live;
proxy_pass http://rtmp;
proxy_http_version 1.1;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 9,7 @@
"autoprefixer": "^9.7.6",
"axios": "^0.19.2",
"core-js": "^3.0.0",
"flv.js": "^1.5.0",
"lodash": "^4.17.15",
"postcss-loader": "^3.0.0",
"regenerator-runtime": "^0.13.2",
Expand Down
8 changes: 8 additions & 0 deletions rtmp_nginx_dev.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 13,14 @@ http {
location /control {
rtmp_control all;
}

location /live {
flv_live on;
chunked_transfer_encoding on;

add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
}
}
}

Expand Down
30 changes: 30 additions & 0 deletions src/Controller/PublicPlayerController.php
Original file line number Diff line number Diff line change
@@ -0,0 1,30 @@
<?php

declare(strict_types=1);

namespace App\Controller;

use App\Repository\StreamRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;

class PublicPlayerController extends AbstractController
{
/**
* @Route("/play/{streamSlug}", name="public_player")
*/
public function index(string $streamSlug, StreamRepository $streamRepository, string $rtmpHttpFlvBaseUrl)
{
$stream = $streamRepository->findOneBySlug($streamSlug);
if (!$stream) {
throw new NotFoundHttpException();
}

$url = $rtmpHttpFlvBaseUrl . '?stream=' . $stream->getSlug();

return $this->render('public_player.html.twig', [
'url' => $url,
]);
}
}
3 changes: 1 addition & 2 deletions src/EntityPublisher.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 31,7 @@ public function publish($entity)
$iri = $this->iriConverter->getIriFromItem($entity);
$update = new Update(
$iri,
$this->serializer->serialize($entity, 'json', ['groups' => ['read']]),
[] // TODO
$this->serializer->serialize($entity, 'json', ['groups' => ['read']])
);
($this->publisher)($update);
}
Expand Down
5 changes: 4 additions & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 8,16 @@ module.exports = {
},
},
},
variants: {},
variants: {
display: ['responsive', 'group-hover'],
},
plugins: [
require('@tailwindcss/ui'),
],
purge: {
content: [
'./assets/js/admin/**/*.vue',
'./templates/**/*.html.twig',
],
options: {
// https://tailwindui.com/documentation#update-your-purgecss-configuration
Expand Down
30 changes: 30 additions & 0 deletions templates/public_player.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<title>Stream Player</title>

<link rel="stylesheet" href="https://rsms.me/inter/inter.css">

{{ encore_entry_link_tags('publicPlayer') }}
</head>
<body>
<div id="buttonWrapper" class="h-screen flex items-center justify-center text-lg text-gray-700">
<button type="button" id="playButton" class="flex flex-col items-center uppercase font-semibold tracking-wide p-4">
<span id="buttonIcon"></span>
Play stream
</button>
</div>

<script type="text/javascript">
var stream_url = '{{ url|raw }}';
</script>
{{ encore_entry_script_tags('publicPlayer') }}
</body>
</html>

{# The following Tailwind classes are used in publicPlayer.js, add them here to #}
{# make sure they are included when running PurgeCSS: #}
{# w-screen h-screen #}
Loading

0 comments on commit cdffde6

Please sign in to comment.