marsha icon indicating copy to clipboard operation
marsha copied to clipboard

Shared media in a webinar

Open lunika opened this issue 3 years ago • 6 comments

Feature Request

Is your feature request related to a problem or unsupported use case? Please describe.

During a Webinar, an instructor wants to share Media with student. The media can be a PDF or any office document. The instructor needs in a first time to upload these documents and once the convert process applied the document can be shared with students.

Backend spec

ShareLiveMedia

A new model must be created to manage this new resource. We can name it SharedLiveMedia, but this name is open to be changed. We will use this name in this issue for now.

ShareLiveMedia model contains following properties:

SharedLiveMedia
id
video_id
upload_state
uploaded_on
nb_pages # This property contains the document's pages
extension
title
show_download

Following API endpoints will be added

POST /api/sharedlivemedias/ GET /api/sharedlivemedias/ # Must be restricted to the current video context (present in the JWT Token) GET /api/sharedlivemedias/{pk}/ POST /api/sharedlivemedias/initiate-upload/

The payload for a single resource will be

{
	"id": "3d6a179c-cf18-47d5-9e8e-a1368a243c2d",
	"video_id": "7cfb42e1-d53e-4a78-b39f-83277fa91a9b",
	"active_stamp": "1638230400",
	"filename": "python-expressions.pdf",
	"is_ready_to_show": true,
	"nb_pages": 3,
	"show_download": true,
	"title": "python expressions",
	"upload_state": "ready",
	"urls": {
		"media": (
			"https://abc.cloudfront.net/d9d7049c-5a3f-4070-a494-e6bf0bd8b9fb/"
			"sharedlivemedias/7520c16b-5846-41ca-822b-52b446a96809/1638230400"
			"/1638230400/1638230400.pdf?response-content-disposition="
			"attachment%3B+filename%3Dpython-expressions.pdf&Expires="
			"1638237600&Signature=A69S6ycsdBnPUNViT6moHzDz-Z~x-OczY6hU9pWqQ1wb"
			"CFeZC06EmwA44aZ62EPeYJr~rBdraLSXJevyk99zPNGPuFinF0XK6ggWannUjrvfk"
			"3Cqyt2ZGSI5QHwpKqo5crHj018SG28DNuA7cXsQ-BjlaSizwtmzJUV2Hcx5fvFDvx"
			"FlSrp3lAHHSdOA~L7N2pn1sTfjgqXRjge7KnJGot-dZnlKAC3wCvuazbuLZmzdA7i"
			"3rVdlNBIMCWhKE5WUUoXlW1tduPTqyqrzfOaoGv2TTsJJqPuEEWVwRRqv0DgRP27S"
			"oL7qzIvG~OeNYrabMuRQoyFDbYpFRt~ZVQRSwA__"
			"&Key-Pair-Id=cloudfront-access-key-id"
		),
		"pages": {
			"1": (
				"https://abc.cloudfront.net/d9d7049c-5a3f-4070-a494-e6bf0bd8b9"
				"fb/sharedlivemedias/7520c16b-5846-41ca-822b-52b446a96809/1638"
				"230400/1.png?Expires=1638237600&Signature=NMUCJsyMGlg1ZQ4ocHj"
				"iqqHveeBcWEt9Hpd-QhSDsPco7iwTwfTS~tgQkjg0OfkZ16hPq118d8AZqXLk"
				"cYvYR32Z5oDdV08P1LTh8ViUgBtz3XV8yxc~VmyQ3-OmFINSBqPXjZLf29bkX"
				"ZaPg9LU~EditKJTaWrfhkpD2GljyXdj7X6uePqFWWVaIlkY4Xl1Dhjk04hjS2"
				"f3m5hictwCCSgN-i8r~EKEeUkVCcdf3TGOFOCcrBlxd9525rzUtvgKMDqlyIK"
				"GEwGAbK10iRI~pnB3EgXWxZ7U~8x-xZT7bmoIrt6NuVKvqf2mNLWWjizGAjOM"
				"D1WpO1EGhhZBTdinNg__&Key-Pair-Id=cloudfront-access-key-id"
			),
			"2": (
				"https://abc.cloudfront.net/d9d7049c-5a3f-4070-a494-e6bf0bd8b9"
				"fb/sharedlivemedias/7520c16b-5846-41ca-822b-52b446a96809/1638"
				"230400/2.png?Expires=1638237600&Signature=Qp3z9GZV5guZxb2jHuB"
				"rbIsYMyKNJ7gMAKyycQusresKjhtwgOJD3hp~vW8b6B1oRRtp~Osb~T5j13Mb"
				"S-XNCjICs3C~7b6p7e77CTg9V6TZF2rQZBz2oOoXiKGAWgkX8adxjFRAImE24"
				"NVsudJtaKpef-4MPgFcSZfI3O9KQadCv4LW6Q~IZDCCl6JHHrDf6SSBggcyr8"
				"sRcXM8dUTM2NWf56siMLk6UmY8BNra4qM9zlO7DDNPT1iGsuUcX2OIgHOVI0y"
				"kH3PIvQ7yWqTCzKMJrP7xfNczWjHBNxrf~rtjbDV5fYO1gdUDlacfPpz4bnu0"
				"1xPn9lUNr3uooIe~UA__&Key-Pair-Id=cloudfront-access-key-id"
			),
			"3": (
				"https://abc.cloudfront.net/d9d7049c-5a3f-4070-a494-e6bf0bd8b9"
				"fb/sharedlivemedias/7520c16b-5846-41ca-822b-52b446a96809/1638"
				"230400/3.png?Expires=1638237600&Signature=G31rnBICbaateEwB8~a"
				"FakNoZQMRE-Urzo-CRAvp~AYsdYNEFlbFgYfe-H6if34sT0TX1h2UpZe2HL8p"
				"bWG0rIuBArYcpLcO9UPncXEBAKnX4WQr8Svl1s-ECBOE3WWC~-Em1o-93ss6q"
				"YHgk3ABlxswysK5GmIGiraF1rjBNzktkZ87cbNAXpllRAl5swt~LAZyGH8bKn"
				"S8reNawGJZo~ppAZEt1cHbpKkfzuoLTKHpuIgkxevzdZCVJ2pPnimAyKQGsYH"
				"55aoLlD-BGcN~oFojDyDD00UUuq9HwRN1xZTYdS0881FSKNkL6Q7AfPkZ6bKP"
				"POmevpdzePDS0Cj-PQ__&Key-Pair-Id=cloudfront-access-key-id"
			),
		},
	},
}

The enpoint GET /api/sharedlivemedias/ will return a collection of sharedlivemedias. This same collection will be side loaded to the video payload.

Video

Video object must be modified to save the shared state. When an instructor start sharing, we must save the sharedlivemedias id shared and every time the page change, the current page must be saved. These informations must be added to the video payload

Start/Stop and navigate in a Media

All the workflow should be managed by django. For this we have to create dedicated endpoints in the Video viewset or in the sharedlivemedias viewset, we have determine this point.

  • start endpoint set in the video object the active sharedlivemedias and the current page to 1. Then django broadcasts an XMPP message to all participants. The XMPP message contains in its body the video serialized in JSON.
  • navigate endpoint changes the current page. This info must be save in the video object. Then django broadcasts an XMPP message to all participants. The XMPP message contains in its body the video serialized in JSON.
  • end endpoint remove active sharedlivemedias in the video object. Then django broadcasts an XMPP message to all participants. The XMPP message contains in its body the video serialized in JSON.

A message broadcasted to all participant must be of type groupchat to the conference url. The event should be one of the 3 actions before and the body the video previously modified and saved.

The current active shared live media id and its current page should be save in the video model with two new fields nullable:

active_shared_live_media = models.ForeignKey(
        "SharedLiveMedia",
        blank=True,
        null=True,
        related_name="video",
        verbose_name=_("Video"),
    )

    active_shared_live_media_page = models.PositiveIntegerField(
        blank=True,
        null=True,
        help_text=_("Current displayed page of the active shared live media"),
    )

This new fields should be added to the video serializer and a shared live media should not be deleted if currently active (also check if there is something to do on the on_delete action on the model)

Convert process

The goal of the convert process is to take a Media in input (PDF, office document, we have to determine a list of supported documents) and convert them in images. One image per document page.

To trigger the the convert process, we will use the already existing workflow we have with the lamda-encode function. The document is uploaded in the source bucket, the lambda-encode function is trigger. During this function the media is converted in image and the generated images are saved in the destination bucket. At the end, the Django application is fetched with the data needed to update the shared media object.

⚠ This process can be long and can consumes lot of resources. Lambda have some limitations (timeout, resources available, etc) and maybe triggering other lambdas or an other function in ECS can be needed.

lambda-encode is not a relevant name anymore. We can rename it in lambda-convert, but this must be done in a dedicated PR, before or after this issue is made.

Front spec

The front is responsible to display the current page when a sharedlivemedias is active. A converse plug-in should be created to listen messages broadcasted in the XMPP conference room. When a message is received and validated (checking the type and the event) the video should be updated in the zustand store with the one received in the message. Updating the store should rerender the component responsible to display the current page.

All the information needed to display the page are present in the video object.

lunika avatar Nov 23 '21 16:11 lunika

Suggestion of tools for the convert process

Most of the library in python or javascript for node are layers on top of commands like soffice or ImageMagick or pdftoppm

The given strategy can be applied to convert a media file into multiple images:

Convert office files in PDF

The first step can be to convert every office files in a PDF. We can accept in input every files from microsoft office or (libre|open)office. We have to test this process with presentation files from Mac OS environment.

The soffice binary provided by libreoffice can be used to do this job. It can converts several input files format into PDF. We have to determine the input format to help him to do a better convert

Here is a details stackoverflow post explaining well hot to use it: https://stackoverflow.com/a/30465397

Convert PDF files in images

Once the media file converted in PDF, we have to convert to an image. Obviously if the original file is already a PDF, we begin directly at this step.

Several command line can be used here:

pdftoppm seems easier to use while ImageMagick convert allows to do more things.

lunika avatar Dec 07 '21 10:12 lunika

For a better conversion from office files to pdf, the last version of libreoffice must be used.

lunika avatar Dec 07 '21 14:12 lunika

@kernicPanel you can continue with Start/Stop and navigate in a Media part. I updated it.

lunika avatar Dec 16 '21 20:12 lunika

All the workflow should be managed by django. For this we have to create dedicated endpoints in the Video viewset or in the sharedlivemedias viewset, we have determine this point.

I think /api/sharedlivemedias/{pk}/start/, for example, would be more intuitive than /api/video/{pk}/start as the "starting action" is more related to the SharedLiveMedia instance than the Video one. Moreover, using the video viewset would force us to always specify the SharedLiveMedia id we want to act on by passing it in POST datas.

WDYT, @lunika ?

kernicPanel avatar Dec 17 '21 07:12 kernicPanel

Ok you can use this endpoint.

I also think we should not allow starting a share while there is already an ongoing share. It's the front responsibility IMO to deal with it. They can stop the current to start the new one. Or ask the user what he wants to do (with a confirmation process), or other scenarios.

lunika avatar Dec 17 '21 08:12 lunika

The django part of this project is done. We can keep open this issue for a record for the front application.

lunika avatar Jan 11 '22 09:01 lunika