Skip to content
This repository has been archived by the owner on Oct 6, 2024. It is now read-only.

Commit

Permalink
Fixes to API video extraction framework.
Browse files Browse the repository at this point in the history
  • Loading branch information
Nyah Check committed Aug 5, 2017
1 parent fcd240f commit 1c0f04f
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 105 deletions.
225 changes: 126 additions & 99 deletions api/apidata.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

package api

import (
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
Expand All @@ -18,7 +21,23 @@ import (
"google.golang.org/api/youtube/v3"
)


//const variables
const (

//Video extractor
videoExtractor = "http://youtube.com/get_video_info?video_id="
)

//Youtube Downloader Data file.
type RawVideoData struct {
Title string `json:"title"`
Author string `json:"author`
Status string `json:"status"`
URLEncodedFmtStreamMap map[string][]string `json:"url_encoded_fmt_stream_map"`
}

}
type ApiData struct {
FileName string
Title string
Expand All @@ -33,16 +52,17 @@ type ApiData struct {
//gets the Video ID from youtube url
func getVideoId(url string) ( string, error) {

s := strings.Split(url, "?v="))
s := strings.Split(url, "?v=")
s = strings.Split(s[1], "&")
if len(s[0]) == 0 {
s[0], error.New("Empty string)
return s[0], errors.New("Empty string")
}

return s[0], nil
}



func printVideosListResults(response *youtube.VideoListResponse) {
for _, item := range response.Items {
fmt.Println(item.Id, ": ", item.Snippet.Title)
Expand All @@ -60,141 +80,148 @@ func videosListById(service *youtube.Service, part string, id string) {
printVideosListResults(response)
}

videosListById(service, "snippet,contentDetails,statistics", "Ks-_Mh1QhMc")




//Gets Video Data from Youtube URL
func APIGetVideoStream(service youtube.Service, url string)(videoData []byte, err error) {

videoStream := new(RawVideoData)

//Gets video Id
id , err := getVideoId(url)
auth.HandleError(err, "Invalid youtube URL.")

//Get Video response stream
videosListById(service, "snippet,contentDetails,liveStreamingDetails, fileDetails", id)//fileDetails part not permitted.
//Get Video Data stream
videoUrl := videoExtractor + id
resp, er := http.Get(videoUrl)
auth.HandleError(er, "Error in GET request)
defer resp.Body.Close()
out, e := ioutil.ReadAll(resp.Body)
auth.HandleError(e, "Error reading video data")
if err = json.Unmarshal(out, &a.output); err != nil {
logrus.Errorf("Error JSON Unmarshall: %v", err)
}
//Extract Video information.
videoInfo := videosListById(service, "snippet,contentDetails", id)//fileDetails part not permitted.

//Get Data stream from video response

if err = json.Unmarshal(out, &videoStream); err != nil {
logrus.Errorf("Error JSON Unmarshall: %v", err)
}

//Download data stream to memory.

//convert video file to flv or mp3


}


//retrieve uploads
func main() {
flag.Parse()

client, err := buildOAuthHTTPClient(youtube.YoutubeReadonlyScope)
if err != nil {
log.Fatalf("Error building OAuth client: %v", err)
}
func ApiDownloadVideo() {


service, err := youtube.New(client)
}



func decodeVideoInfo(response string) (streams streamList, err error) {
// decode

answer, err := url.ParseQuery(response)
if err != nil {
log.Fatalf("Error creating YouTube client: %v", err)
err = fmt.Errorf("parsing the server's answer: '%s'", err)
return
}

// Start making YouTube API calls.
// Call the channels.list method. Set the mine parameter to true to
// retrieve the playlist ID for uploads to the authenticated user's
// channel.
call := service.Channels.List("contentDetails").Mine(true)
// check the status

response, err := call.Do()
err = ensureFields(answer, []string{"status", "url_encoded_fmt_stream_map", "title", "author"})
if err != nil {
// The channels.list method call returned an error.
log.Fatalf("Error making API call to list channels: %v", err.Error())
err = fmt.Errorf("Missing fields in the server's answer: '%s'", err)
return
}

for _, channel := range response.Items {
playlistId := channel.ContentDetails.RelatedPlaylists.Uploads
// Print the playlist ID for the list of uploaded videos.
fmt.Printf("Videos in list %s\r\n", playlistId)

nextPageToken := ""
for {
// Call the playlistItems.list method to retrieve the
// list of uploaded videos. Each request retrieves 50
// videos until all videos have been retrieved.
playlistCall := service.PlaylistItems.List("snippet").
PlaylistId(playlistId).
MaxResults(50).
PageToken(nextPageToken)

playlistResponse, err := playlistCall.Do()

if err != nil {
// The playlistItems.list method call returned an error.
log.Fatalf("Error fetching playlist items: %v", err.Error())
}

for _, playlistItem := range playlistResponse.Items {
title := playlistItem.Snippet.Title
videoId := playlistItem.Snippet.ResourceId.VideoId
fmt.Printf("%v, (%v)\r\n", title, videoId)
}

// Set the token to retrieve the next page of results
// or exit the loop if all results have been retrieved.
nextPageToken = playlistResponse.NextPageToken
if nextPageToken == "" {
break
}
fmt.Println()
status := answer["status"]
if status[0] == "fail" {
reason, ok := answer["reason"]
if ok {
err = fmt.Errorf("'fail' response status found in the server's answer, reason: '%s'", reason[0])
} else {
err = errors.New(fmt.Sprint("'fail' response status found in the server's answer, no reason given"))
}
return
}
if status[0] != "ok" {
err = fmt.Errorf("non-success response status found in the server's answer (status: '%s')", status)
return
}
}

func ApiDownloadVideo() {
log("Server answered with a success code")

/*
for k, v := range answer {
log("%s: %#v", k, v)
}
*/

}main() {
flag.Parse()
// read the streams map

if *filename == "" {
log.Fatalf("You must provide a filename of a video file to upload")
}
stream_map := answer["url_encoded_fmt_stream_map"]

client, err := buildOAuthHTTPClient(youtube.YoutubeUploadScope)
if err != nil {
log.Fatalf("Error building OAuth client: %v", err)
}
// read each stream

service, err := youtube.New(client)
if err != nil {
log.Fatalf("Error creating YouTube client: %v", err)
}
streams_list := strings.Split(stream_map[0], ",")

upload := &youtube.Video{
Snippet: &youtube.VideoSnippet{
Title: *title,
Description: *description,
CategoryId: *category,
},
Status: &youtube.VideoStatus{PrivacyStatus: *privacy},
}
log("Found %d streams in answer", len(streams_list))

// The API returns a 400 Bad Request response if tags is an empty string.
if strings.Trim(*keywords, "") != "" {
upload.Snippet.Tags = strings.Split(*keywords, ",")
}
for stream_pos, stream_raw := range streams_list {
stream_qry, err := url.ParseQuery(stream_raw)
if err != nil {
log(fmt.Sprintf("An error occured while decoding one of the video's stream's information: stream %d: %s\n", stream_pos, err))
continue
}
err = ensureFields(stream_qry, []string{"quality", "type", "url"})
if err != nil {
log(fmt.Sprintf("Missing fields in one of the video's stream's information: stream %d: %s\n", stream_pos, err))
continue
}
/* dumps the raw streams
log(fmt.Sprintf("%v\n", stream_qry))
*/
stream := stream{
"quality": stream_qry["quality"][0],
"type": stream_qry["type"][0],
"url": stream_qry["url"][0],
"sig": "",
"title": answer["title"][0],
"author": answer["author"][0],
}

if sig, exists := stream_qry["sig"]; exists { // old one
stream["sig"] = sig[0]
}

if sig, exists := stream_qry["s"]; exists { // now they use this
stream["sig"] = sig[0]
}

streams = append(streams, stream)

call := service.Videos.Insert("snippet,status", upload)
quality := stream.Quality()
if quality == QUALITY_UNKNOWN {
log("Found unknown quality '%s'", stream["quality"])
}

file, err := os.Open(*filename)
defer file.Close()
if err != nil {
log.Fatalf("Error opening %v: %v", *filename, err)
}
format := stream.Format()
if format == FORMAT_UNKNOWN {
log("Found unknown format '%s'", stream["type"])
}

response, err := call.Media(file).Do()
if err != nil {
log.Fatalf("Error making YouTube API call: %v", err)
log("Stream found: quality '%s', format '%s'", quality, format)
}
fmt.Printf("Upload successful! Video ID: %v\n", response.Id)
}

log("Successfully decoded %d streams", len(streams))

return
}
35 changes: 29 additions & 6 deletions simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
package main

import (
"encoding/json"
"fmt"
//"io/ioutil"
"log"
"io/ioutil"
//"log"
"net/http"

"github.com/Sirupsen/logrus"

"google.golang.org/api/googleapi/transport"
youtube "google.golang.org/api/youtube/v3"
Expand All @@ -18,25 +21,45 @@ const developerKey = "AIzaSyCZSy5sOGsZrOrI0vLtowf_VJ-tl_USzNE"

func main() {

videoExtractor := "https://youtube.com/get_video_info?video_id="
var dat map[string]interface{}
id := "Ks-_Mh1QhMc"


client := &http.Client{
Transport: &transport.APIKey{Key: developerKey},
}

service, err := youtube.New(client)
if err != nil {
log.Fatalf("Error creating new YouTube client: %v", err)
logrus.Fatalf("Error creating new YouTube client: %v", err)
}

// Make GET request to Youtube API.
call := service.Videos.List("snippet, recordingDetails")
call.Id("Ks-_Mh1QhMc")
call := service.Videos.List("snippet, contentDetails, liveStreamingDetails, player")
call.Id(id)
resp, err := call.Do()
if err != nil {
log.Fatalf("Error getting Video response: %v", err)
logrus.Fatalf("Error getting Video response: %v", err)
}
for cnt, item := range resp.Items {
fmt.Printf("\n %d: %+v\n", cnt, item)
}

logrus.Infof("Starting the Video extration process.")

//Get Video Data stream
videoUrl := videoExtractor + id
res, er := http.Get(videoUrl)
logrus.Fatalf("Error in GET request: %v", er)
defer res.Body.Close()
out, e := ioutil.ReadAll(res.Body)
logrus.Fatalf("Error reading video data", e)
if err = json.Unmarshal(out, &dat); err != nil {
logrus.Errorf("Error JSON Unmarshall: %v", err)
}

fmt.Println(dat)

return
}

0 comments on commit 1c0f04f

Please sign in to comment.