└── screenshooter
├── description.yaml
├── README.md
├── __init__.py
└── main.js
/screenshooter/description.yaml:
--------------------------------------------------------------------------------
1 | Type: Jupyter Notebook Extension
2 | Compatibility: 3.x, 4.x, 5.x, 6.x
3 | Name: Screen shooter
4 | Main: main.js
5 | Link: README.md
6 | Description: |
7 | Adds the ability to easily take screenshots and save them into the notebook.
8 |
9 | Parameters:
10 | - none
11 |
--------------------------------------------------------------------------------
/screenshooter/README.md:
--------------------------------------------------------------------------------
1 | Screen shooter
2 |
3 | =========
4 |
5 | Adds the ability to easily take screenshots and save them into the notebook.
6 | to use:
7 | * click the button
8 | * select the capture source (e.g. full screen, a specific application, etc...)
9 | * A cell will be added (above the currently selected cell) with the screenshot
10 |
11 | This extenstion is a work in progress to assist with workflow documentation.
12 |
--------------------------------------------------------------------------------
/screenshooter/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 | from glob import glob
3 |
4 | from setuptools import find_packages, setup
5 |
6 | setup(
7 | name='screen_shooter_nbextension',
8 | version='0.1dev',
9 | license='Creative Commons Attribution-Noncommercial-Share Alike license',
10 | long_description="Adds the ability to easily take screenshots and save them into the notebook.",
11 | author='mstern',
12 |
13 | packages=['screenshooter',],
14 | install_requires=[
15 | 'jupyter_core',
16 | 'notebook >=4.0',
17 | ],
18 | # jupyter server
19 | zip_safe=False,
20 | include_package_data=True,
21 | data_files=[
22 | # like `jupyter nbextension install --sys-prefix`
23 | ("share/jupyter/nbextensions/screenshooter", [
24 | "screenshooter/static/index.js",
25 | ]),
26 | # like `jupyter nbextension enable --sys-prefix`
27 | ("etc/jupyter/nbconfig/notebook.d", [
28 | "jupyter-config/nbconfig/notebook.d/screenshooter.json"
29 | ]),
30 | # like `jupyter serverextension enable --sys-prefix`
31 | ("etc/jupyter/jupyter_notebook_config.d", [
32 | "jupyter-config/jupyter_notebook_config.d/screenshooter.json"
33 | ])
34 | ]
35 | )
36 |
37 |
38 | if __name__ == '__main__':
39 | main()
40 |
--------------------------------------------------------------------------------
/screenshooter/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'base/js/namespace',
3 | 'base/js/events'
4 | ], function(Jupyter, events) {
5 |
6 | // Adds a cell above current cell (will be top if no cells)
7 | var add_cell = function() {
8 | const uuid = UID();
9 |
10 | $(`
11 |
12 |
![]()
13 |
`).appendTo(document.body);
14 |
15 | Jupyter.notebook.insert_cell_above('markdown').set_text("\nscreenshot");
16 | Jupyter.notebook.select_prev();
17 | CaptureNow(uuid);
18 | };
19 | // Button to add default cell
20 | var defaultCellButton = function () {
21 | Jupyter.toolbar.add_buttons_group([
22 | Jupyter.keyboard_manager.actions.register ({
23 | 'help': 'take screenshot',
24 | 'icon' : 'fa-image',
25 | 'handler': add_cell
26 | }, 'screenshooter', 'screen shot')
27 | ])
28 | };
29 | var prefix = 'screenShooter';
30 | var action_name = 'take_screenShot';
31 |
32 | // Run on start
33 | function load_ipython_extension() {
34 | defaultCellButton();
35 | }
36 |
37 | var UID = function () {
38 | // generates a random ID so we can easily have multiple screenshots saved
39 | return '_' + Math.random().toString(36).substr(2, 9);
40 | };
41 | /* Main Screen shooter */
42 | function CaptureNow(uuid) {
43 | // connect to image & video
44 | console.log('screenshot '+uuid+' capturing');
45 | var videoElem = document.getElementById("video"+uuid);
46 | var image = document.getElementById("image"+uuid);
47 | var ourDiv = document.getElementById("section"+uuid);
48 | // hey user select what they want to capture
49 | navigator.mediaDevices.getDisplayMedia({
50 | audio: false,
51 | video: true
52 | })
53 | .then(mediaStream => {
54 | videoElem.srcObject = mediaStream;
55 | // Stop the stream after .1 seconds
56 | setTimeout(() => {
57 | const tracks = mediaStream.getTracks()
58 | tracks[0].stop()
59 | }, 100)
60 | return videoElem.play();
61 | }).then(() => { // enable the button
62 | takeASnap(videoElem, image);
63 | ourDiv.remove();
64 | })
65 | };
66 | /* Helper methods to take screenshot */
67 | function takeASnap(videoElem, image) {
68 | const canvas = document.createElement('canvas'); // create a canvas
69 | const ctx = canvas.getContext('2d'); // get its context
70 | canvas.width = videoElem.videoWidth; // set its size to the one of the video
71 | canvas.height = videoElem.videoHeight;
72 | ctx.drawImage(videoElem, 0, 0); // the video
73 |
74 | canvas.toBlob(download(image), 'image/jpeg');
75 | // return new Promise((res, rej) => {
76 | // canvas.toBlob(res, 'image/jpeg'); // request a Blob from the canvas
77 | // });
78 | }
79 |
80 | function download(image) {
81 | // ad to img tag
82 | return function(blob) {
83 | console.log( blob );
84 | Jupyter.notebook.get_selected_cell().
85 | insert_inline_image_from_blob(blob);
86 |
87 | setTimeout(function(){
88 | Jupyter.notebook.execute_cell_and_select_below();
89 | }, 500);
90 |
91 | var reader = new FileReader();
92 | reader.readAsDataURL(blob);
93 | reader.onloadend = function() {
94 | image.src = reader.result;
95 | }
96 | }
97 | }
98 |
99 | return {
100 | load_ipython_extension: load_ipython_extension
101 | };
102 | });
103 |
--------------------------------------------------------------------------------